all: require calling `optfn() ?` / `optfn() or {...}` for `fn optfn() ? {}`
parent
97103f680a
commit
e5a84719ca
|
@ -70,7 +70,8 @@ fn main() {
|
|||
date := time.unix(commit_date.int())
|
||||
mut out := os.create('table.html') ?
|
||||
// Place the new row on top
|
||||
table = '<tr>
|
||||
table =
|
||||
'<tr>
|
||||
<td>$date.format()</td>
|
||||
<td><a target=_blank href="https://github.com/vlang/v/commit/$commit">$commit</a></td>
|
||||
<td>$message</td>
|
||||
|
@ -80,15 +81,15 @@ fn main() {
|
|||
<td>${diff4}ms</td>
|
||||
</tr>\n' +
|
||||
table.trim_space()
|
||||
out.writeln(table)
|
||||
out.writeln(table) ?
|
||||
out.close()
|
||||
// Regenerate index.html
|
||||
header := os.read_file('header.html') ?
|
||||
footer := os.read_file('footer.html') ?
|
||||
mut res := os.create('index.html') ?
|
||||
res.writeln(header)
|
||||
res.writeln(table)
|
||||
res.writeln(footer)
|
||||
res.writeln(header) ?
|
||||
res.writeln(table) ?
|
||||
res.writeln(footer) ?
|
||||
res.close()
|
||||
}
|
||||
exec('git checkout master')
|
||||
|
@ -96,9 +97,7 @@ fn main() {
|
|||
}
|
||||
|
||||
fn exec(s string) string {
|
||||
e := os.exec(s) or {
|
||||
panic(err)
|
||||
}
|
||||
e := os.exec(s) or { panic(err) }
|
||||
return e.output.trim_right('\r\n')
|
||||
}
|
||||
|
||||
|
@ -112,7 +111,7 @@ fn measure(cmd string, description string) int {
|
|||
println(' Building...')
|
||||
mut runs := []int{}
|
||||
for r in 0 .. 5 {
|
||||
println(' Sample ${r+1}/5')
|
||||
println(' Sample ${r + 1}/5')
|
||||
sw := time.new_stopwatch({})
|
||||
exec(cmd)
|
||||
runs << int(sw.elapsed().milliseconds())
|
||||
|
|
|
@ -12,21 +12,20 @@ pub fn set_verbose(on bool) {
|
|||
// but V does not have globals normally.
|
||||
if on {
|
||||
os.setenv('VERBOSE', '1', true)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
os.unsetenv('VERBOSE')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cprintln(message string) {
|
||||
mut omessage := message
|
||||
omessage = if term_colors { term.green(omessage) } else { omessage }
|
||||
omessage = if scripting.term_colors { term.green(omessage) } else { omessage }
|
||||
println(omessage)
|
||||
}
|
||||
|
||||
pub fn verbose_trace(label string, message string) {
|
||||
if os.getenv('VERBOSE').len > 0 {
|
||||
slabel := 'scripting.${label}'
|
||||
slabel := 'scripting.$label'
|
||||
cprintln('# ${slabel:-25s} : $message')
|
||||
}
|
||||
}
|
||||
|
@ -54,9 +53,9 @@ pub fn rmrf(path string) {
|
|||
verbose_trace(@FN, 'rm -rf $path')
|
||||
if os.exists(path) {
|
||||
if os.is_dir(path) {
|
||||
os.rmdir_all(path)
|
||||
}else{
|
||||
os.rm(path)
|
||||
os.rmdir_all(path) or { panic(err) }
|
||||
} else {
|
||||
os.rm(path) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +96,7 @@ pub fn exit_0_status(cmd string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
pub fn tool_must_exist (toolcmd string) {
|
||||
pub fn tool_must_exist(toolcmd string) {
|
||||
verbose_trace(@FN, toolcmd)
|
||||
if exit_0_status('type $toolcmd') {
|
||||
return
|
||||
|
|
|
@ -210,7 +210,7 @@ pub fn (mut ts TestSession) test() {
|
|||
// cleanup generated .tmp.c files after successfull tests:
|
||||
if ts.benchmark.nfail == 0 {
|
||||
if ts.rm_binaries {
|
||||
os.rmdir_all(ts.vtmp_dir)
|
||||
os.rmdir_all(ts.vtmp_dir) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,7 @@ fn worker_trunner(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
|||
generated_binary_fpath := os.join_path(tmpd, generated_binary_fname)
|
||||
if os.exists(generated_binary_fpath) {
|
||||
if ts.rm_binaries {
|
||||
os.rm(generated_binary_fpath)
|
||||
os.rm(generated_binary_fpath) or { panic(err) }
|
||||
}
|
||||
}
|
||||
mut cmd_options := [ts.vargs]
|
||||
|
@ -294,7 +294,7 @@ fn worker_trunner(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
|||
}
|
||||
if os.exists(generated_binary_fpath) {
|
||||
if ts.rm_binaries {
|
||||
os.rm(generated_binary_fpath)
|
||||
os.rm(generated_binary_fpath) or { panic(err) }
|
||||
}
|
||||
}
|
||||
return sync.no_result
|
||||
|
@ -422,7 +422,7 @@ pub fn header(msg string) {
|
|||
pub fn setup_new_vtmp_folder() string {
|
||||
now := time.sys_mono_now()
|
||||
new_vtmp_dir := os.join_path(os.temp_dir(), 'v', 'test_session_$now')
|
||||
os.mkdir_all(new_vtmp_dir)
|
||||
os.mkdir_all(new_vtmp_dir) or { panic(err) }
|
||||
os.setenv('VTMP', new_vtmp_dir, true)
|
||||
return new_vtmp_dir
|
||||
}
|
||||
|
|
|
@ -28,26 +28,26 @@ fn get_vexe_path() string {
|
|||
fn new_tdir() string {
|
||||
tdir_ := os.join_path(os.temp_dir(), rand.ulid())
|
||||
if os.exists(tdir_) {
|
||||
os.rmdir(tdir_)
|
||||
os.rmdir(tdir_) or { panic(err) }
|
||||
}
|
||||
os.mkdir(tdir_)
|
||||
os.mkdir(tdir_) or { panic(err) }
|
||||
C.atexit(cleanup_tdir)
|
||||
return tdir_
|
||||
}
|
||||
|
||||
fn cleanup_tdir() {
|
||||
println('... removing tdir: $tdir')
|
||||
os.rmdir_all(tdir)
|
||||
os.rmdir_all(tdir) or { panic(err) }
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('> vroot: $vroot | vexe: $vexe | tdir: $tdir')
|
||||
ok_fpath := os.join_path(tdir, 'single_test.v')
|
||||
os.write_file(ok_fpath, 'fn test_ok(){ assert true }')
|
||||
os.write_file(ok_fpath, 'fn test_ok(){ assert true }') ?
|
||||
check_ok('"$vexe" $ok_fpath')
|
||||
check_ok('"$vexe" test $ok_fpath')
|
||||
fail_fpath := os.join_path(tdir, 'failing_test.v')
|
||||
os.write_file(fail_fpath, 'fn test_fail(){ assert 1 == 2 }')
|
||||
os.write_file(fail_fpath, 'fn test_fail(){ assert 1 == 2 }') ?
|
||||
check_fail('"$vexe" $fail_fpath')
|
||||
check_fail('"$vexe" test $fail_fpath')
|
||||
check_fail('"$vexe" test $tdir')
|
||||
|
|
|
@ -68,7 +68,6 @@ fn (context Context) file2v(bname string, fbytes []byte, bn_max int) string {
|
|||
sb.write('$b, ')
|
||||
line_len += b.len + 2
|
||||
}
|
||||
|
||||
}
|
||||
sb.write(']!\n')
|
||||
return sb.str()
|
||||
|
@ -76,8 +75,8 @@ fn (context Context) file2v(bname string, fbytes []byte, bn_max int) string {
|
|||
|
||||
fn (context Context) bname_and_bytes(file string) ?(string, []byte) {
|
||||
fname := os.file_name(file)
|
||||
fname_escpaed := fname.replace_each(['.', '_', '-', '_'])
|
||||
byte_name := '$context.prefix$fname_escpaed'.to_lower()
|
||||
fname_escaped := fname.replace_each(['.', '_', '-', '_'])
|
||||
byte_name := '$context.prefix$fname_escaped'.to_lower()
|
||||
fbytes := os.read_bytes(file) or { return error('Error: $err') }
|
||||
return byte_name, fbytes
|
||||
}
|
||||
|
@ -131,12 +130,12 @@ fn main() {
|
|||
}
|
||||
max_bname := context.max_bname_len(file_byte_map.keys())
|
||||
if context.write_file.len > 0 {
|
||||
mut out_file := os.create(context.write_file) or { panic(err) }
|
||||
out_file.write_str(context.header())
|
||||
mut out_file := os.create(context.write_file) ?
|
||||
out_file.write_str(context.header()) ?
|
||||
for bname, fbytes in file_byte_map {
|
||||
out_file.write_str(context.file2v(bname, fbytes, max_bname))
|
||||
out_file.write_str(context.file2v(bname, fbytes, max_bname)) ?
|
||||
}
|
||||
out_file.write_str(context.footer())
|
||||
out_file.write_str(context.footer()) ?
|
||||
} else {
|
||||
print(context.header())
|
||||
for bname, fbytes in file_byte_map {
|
||||
|
|
|
@ -55,9 +55,14 @@ fn main() {
|
|||
//
|
||||
tpath := os.join_path(session.vtmp_dir, texe)
|
||||
if tname in tools_in_subfolders {
|
||||
os.mv_by_cp(tpath, os.join_path(tfolder, tname, texe))
|
||||
os.mv_by_cp(tpath, os.join_path(tfolder, tname, texe)) or { panic(err) }
|
||||
continue
|
||||
}
|
||||
os.mv_by_cp(tpath, os.join_path(tfolder, texe)) or {
|
||||
if !err.contains('vbuild-tools') {
|
||||
eprintln(err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
os.mv_by_cp(tpath, os.join_path(tfolder, texe))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ fn (c &Create) write_vmod(new bool) {
|
|||
cerror(err)
|
||||
exit(1)
|
||||
}
|
||||
vmod.write_str(vmod_content(c.name, c.description))
|
||||
vmod.write_str(vmod_content(c.name, c.description)) or { panic(err) }
|
||||
vmod.close()
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,12 @@ fn (c &Create) write_main(new bool) {
|
|||
return
|
||||
}
|
||||
main_path := if new { '$c.name/${c.name}.v' } else { '${c.name}.v' }
|
||||
mut main := os.create(main_path) or {
|
||||
mut mainfile := os.create(main_path) or {
|
||||
cerror(err)
|
||||
exit(2)
|
||||
}
|
||||
main.write_str(main_content())
|
||||
main.close()
|
||||
mainfile.write_str(main_content()) or { panic(err) }
|
||||
mainfile.close()
|
||||
}
|
||||
|
||||
fn (c &Create) create_git_repo(dir string) {
|
||||
|
@ -87,7 +87,7 @@ fn (c &Create) create_git_repo(dir string) {
|
|||
// We don't really need a .gitignore, it's just a nice-to-have
|
||||
return
|
||||
}
|
||||
fl.write_str(gen_gitignore(c.name))
|
||||
fl.write_str(gen_gitignore(c.name)) or { panic(err) }
|
||||
fl.close()
|
||||
}
|
||||
}
|
||||
|
@ -110,9 +110,7 @@ fn create() {
|
|||
}
|
||||
c.description = os.input('Input your project description: ')
|
||||
println('Initialising ...')
|
||||
os.mkdir(c.name) or {
|
||||
panic(err)
|
||||
}
|
||||
os.mkdir(c.name) or { panic(err) }
|
||||
c.write_vmod(true)
|
||||
c.write_main(true)
|
||||
c.create_git_repo(c.name)
|
||||
|
|
|
@ -126,7 +126,7 @@ fn (vd VDoc) render_search_index(out Output) {
|
|||
js_search_index.writeln('];')
|
||||
js_search_data.writeln('];')
|
||||
out_file_path := os.join_path(out.path, 'search_index.js')
|
||||
os.write_file(out_file_path, js_search_index.str() + js_search_data.str())
|
||||
os.write_file(out_file_path, js_search_index.str() + js_search_data.str()) or { panic(err) }
|
||||
}
|
||||
|
||||
fn (mut vd VDoc) render_static_html(out Output) {
|
||||
|
@ -162,7 +162,7 @@ fn (vd VDoc) get_resource(name string, out Output) string {
|
|||
output_path := os.join_path(out.path, name)
|
||||
if !os.exists(output_path) {
|
||||
println('Generating $out.typ in "$output_path"')
|
||||
os.write_file(output_path, res)
|
||||
os.write_file(output_path, res) or { panic(err) }
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ fn (vd VDoc) work_processor(mut work sync.Channel, mut wg sync.WaitGroup) {
|
|||
file_name, content := vd.render_doc(pdoc.d, pdoc.out)
|
||||
output_path := os.join_path(pdoc.out.path, file_name)
|
||||
println('Generating $pdoc.out.typ in "$output_path"')
|
||||
os.write_file(output_path, content)
|
||||
os.write_file(output_path, content) or { panic(err) }
|
||||
}
|
||||
wg.done()
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
|
|||
os.mkdir(out.path) or { panic(err) }
|
||||
} else {
|
||||
for fname in css_js_assets {
|
||||
os.rm(os.join_path(out.path, fname))
|
||||
os.rm(os.join_path(out.path, fname)) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ fn (mut vd VDoc) generate_docs_from_file() {
|
|||
for favicon in favicons {
|
||||
favicon_path := os.join_path(favicons_path, favicon)
|
||||
destination_path := os.join_path(out.path, favicon)
|
||||
os.cp(favicon_path, destination_path)
|
||||
os.cp(favicon_path, destination_path) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ fn (foptions &FormatOptions) format_file(file string) {
|
|||
file_name := os.file_name(file)
|
||||
ulid := rand.ulid()
|
||||
vfmt_output_path := os.join_path(vtmp_folder, 'vfmt_${ulid}_$file_name')
|
||||
os.write_file(vfmt_output_path, formatted_content)
|
||||
os.write_file(vfmt_output_path, formatted_content) or { panic(err) }
|
||||
if foptions.is_verbose {
|
||||
eprintln('fmt.fmt worked and $formatted_content.len bytes were written to $vfmt_output_path .')
|
||||
}
|
||||
|
@ -258,7 +258,8 @@ fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path
|
|||
}
|
||||
|
||||
fn (f FormatOptions) str() string {
|
||||
return 'FormatOptions{ is_l: $f.is_l, is_w: $f.is_w, is_diff: $f.is_diff, is_verbose: $f.is_verbose,' +
|
||||
return
|
||||
'FormatOptions{ is_l: $f.is_l, is_w: $f.is_w, is_diff: $f.is_diff, is_verbose: $f.is_verbose,' +
|
||||
' is_all: $f.is_all, is_worker: $f.is_worker, is_debug: $f.is_debug, is_noerror: $f.is_noerror,' +
|
||||
' is_verify: $f.is_verify" }'
|
||||
}
|
||||
|
|
|
@ -71,9 +71,7 @@ fn main() {
|
|||
'install' {
|
||||
if module_names.len == 0 && os.exists('./v.mod') {
|
||||
println('Detected v.mod file inside the project directory. Using it...')
|
||||
manifest := vmod.from_file('./v.mod') or {
|
||||
panic(err)
|
||||
}
|
||||
manifest := vmod.from_file('./v.mod') or { panic(err) }
|
||||
module_names = manifest.dependencies
|
||||
}
|
||||
vpm_install(module_names)
|
||||
|
@ -227,15 +225,11 @@ fn vpm_update(m []string) {
|
|||
}
|
||||
mut errors := 0
|
||||
for name in module_names {
|
||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
||||
continue
|
||||
}
|
||||
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||
os.chdir(final_module_path)
|
||||
println('Updating module "$name"...')
|
||||
verbose_println(' work folder: $final_module_path')
|
||||
vcs := vcs_used_in_dir(final_module_path) or {
|
||||
continue
|
||||
}
|
||||
vcs := vcs_used_in_dir(final_module_path) or { continue }
|
||||
vcs_cmd := supported_vcs_update_cmds[vcs[0]]
|
||||
verbose_println(' command: $vcs_cmd')
|
||||
vcs_res := os.exec('$vcs_cmd') or {
|
||||
|
@ -265,13 +259,9 @@ fn get_outdated() ?[]string {
|
|||
module_names := get_installed_modules()
|
||||
mut outdated := []string{}
|
||||
for name in module_names {
|
||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
||||
continue
|
||||
}
|
||||
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||
os.chdir(final_module_path)
|
||||
vcs := vcs_used_in_dir(final_module_path) or {
|
||||
continue
|
||||
}
|
||||
vcs := vcs_used_in_dir(final_module_path) or { continue }
|
||||
vcs_cmd_steps := supported_vcs_outdated_steps[vcs[0]]
|
||||
mut outputs := []string{}
|
||||
for step in vcs_cmd_steps {
|
||||
|
@ -296,9 +286,7 @@ fn get_outdated() ?[]string {
|
|||
}
|
||||
|
||||
fn vpm_upgrade() {
|
||||
outdated := get_outdated() or {
|
||||
exit(1)
|
||||
}
|
||||
outdated := get_outdated() or { exit(1) }
|
||||
if outdated.len > 0 {
|
||||
vpm_update(outdated)
|
||||
} else {
|
||||
|
@ -307,9 +295,7 @@ fn vpm_upgrade() {
|
|||
}
|
||||
|
||||
fn vpm_outdated() {
|
||||
outdated := get_outdated() or {
|
||||
exit(1)
|
||||
}
|
||||
outdated := get_outdated() or { exit(1) }
|
||||
if outdated.len > 0 {
|
||||
println('Outdated modules:')
|
||||
for m in outdated {
|
||||
|
@ -342,18 +328,16 @@ fn vpm_remove(module_names []string) {
|
|||
exit(2)
|
||||
}
|
||||
for name in module_names {
|
||||
final_module_path := valid_final_path_of_existing_module(name) or {
|
||||
continue
|
||||
}
|
||||
final_module_path := valid_final_path_of_existing_module(name) or { continue }
|
||||
println('Removing module "$name"...')
|
||||
verbose_println('removing folder $final_module_path')
|
||||
os.rmdir_all(final_module_path)
|
||||
os.rmdir_all(final_module_path) or { panic(err) }
|
||||
// delete author directory if it is empty
|
||||
author := name.split('.')[0]
|
||||
author_dir := os.real_path(os.join_path(settings.vmodules_path, author))
|
||||
if os.is_dir_empty(author_dir) {
|
||||
verbose_println('removing author folder $author_dir')
|
||||
os.rmdir(author_dir)
|
||||
os.rmdir(author_dir) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -380,9 +364,7 @@ fn valid_final_path_of_existing_module(name string) ?string {
|
|||
fn ensure_vmodules_dir_exist() {
|
||||
if !os.is_dir(settings.vmodules_path) {
|
||||
println('Creating $settings.vmodules_path/ ...')
|
||||
os.mkdir(settings.vmodules_path) or {
|
||||
panic(err)
|
||||
}
|
||||
os.mkdir(settings.vmodules_path) or { panic(err) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,9 +387,7 @@ fn vcs_used_in_dir(dir string) ?[]string {
|
|||
}
|
||||
|
||||
fn get_installed_modules() []string {
|
||||
dirs := os.ls(settings.vmodules_path) or {
|
||||
return []
|
||||
}
|
||||
dirs := os.ls(settings.vmodules_path) or { return [] }
|
||||
mut modules := []string{}
|
||||
for dir in dirs {
|
||||
adir := os.join_path(settings.vmodules_path, dir)
|
||||
|
@ -420,13 +400,9 @@ fn get_installed_modules() []string {
|
|||
continue
|
||||
}
|
||||
author := dir
|
||||
mods := os.ls(adir) or {
|
||||
continue
|
||||
}
|
||||
mods := os.ls(adir) or { continue }
|
||||
for m in mods {
|
||||
vcs_used_in_dir(os.join_path(adir, m)) or {
|
||||
continue
|
||||
}
|
||||
vcs_used_in_dir(os.join_path(adir, m)) or { continue }
|
||||
modules << '${author}.$m'
|
||||
}
|
||||
}
|
||||
|
@ -435,9 +411,7 @@ fn get_installed_modules() []string {
|
|||
|
||||
fn get_all_modules() []string {
|
||||
url := get_working_server_url()
|
||||
r := http.get(url) or {
|
||||
panic(err)
|
||||
}
|
||||
r := http.get(url) or { panic(err) }
|
||||
if r.status_code != 200 {
|
||||
println('Failed to search vpm.vlang.io. Status code: $r.status_code')
|
||||
exit(1)
|
||||
|
@ -476,9 +450,7 @@ fn resolve_dependencies(name string, module_path string, module_names []string)
|
|||
if !os.exists(vmod_path) {
|
||||
return
|
||||
}
|
||||
data := os.read_file(vmod_path) or {
|
||||
return
|
||||
}
|
||||
data := os.read_file(vmod_path) or { return }
|
||||
vmod := parse_vmod(data)
|
||||
mut deps := []string{}
|
||||
// filter out dependencies that were already specified by the user
|
||||
|
@ -502,9 +474,7 @@ fn parse_vmod(data string) Vmod {
|
|||
'deps': ''
|
||||
}
|
||||
for key in keys {
|
||||
mut key_index := data.index('$key:') or {
|
||||
continue
|
||||
}
|
||||
mut key_index := data.index('$key:') or { continue }
|
||||
key_index += key.len + 1
|
||||
m[key] = data[key_index..data.index_after('\n', key_index)].trim_space().replace("'",
|
||||
'').replace('[', '').replace(']', '')
|
||||
|
@ -519,7 +489,11 @@ fn parse_vmod(data string) Vmod {
|
|||
}
|
||||
|
||||
fn get_working_server_url() string {
|
||||
server_urls := if settings.server_urls.len > 0 { settings.server_urls } else { default_vpm_server_urls }
|
||||
server_urls := if settings.server_urls.len > 0 {
|
||||
settings.server_urls
|
||||
} else {
|
||||
default_vpm_server_urls
|
||||
}
|
||||
for url in server_urls {
|
||||
verbose_println('Trying server url: $url')
|
||||
http.head(url) or {
|
||||
|
@ -572,13 +546,11 @@ fn get_module_meta_info(name string) ?Mod {
|
|||
continue
|
||||
}
|
||||
if r.status_code == 404 || r.text.contains('404') {
|
||||
errors <<
|
||||
'Skipping module "$name", since $server_url reported that "$name" does not exist.'
|
||||
errors << 'Skipping module "$name", since $server_url reported that "$name" does not exist.'
|
||||
continue
|
||||
}
|
||||
if r.status_code != 200 {
|
||||
errors <<
|
||||
'Skipping module "$name", since $server_url responded with $r.status_code http status code. Please try again later.'
|
||||
errors << 'Skipping module "$name", since $server_url responded with $r.status_code http status code. Please try again later.'
|
||||
continue
|
||||
}
|
||||
s := r.text
|
||||
|
|
|
@ -109,21 +109,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
|||
if !is_stdin_a_pipe {
|
||||
println('')
|
||||
}
|
||||
os.rm(file)
|
||||
os.rm(temp_file)
|
||||
$if windows {
|
||||
os.rm(file[..file.len - 2] + '.exe')
|
||||
os.rm(temp_file[..temp_file.len - 2] + '.exe')
|
||||
$if msvc {
|
||||
os.rm(file[..file.len - 2] + '.ilk')
|
||||
os.rm(file[..file.len - 2] + '.pdb')
|
||||
os.rm(temp_file[..temp_file.len - 2] + '.ilk')
|
||||
os.rm(temp_file[..temp_file.len - 2] + '.pdb')
|
||||
}
|
||||
} $else {
|
||||
os.rm(file[..file.len - 2])
|
||||
os.rm(temp_file[..temp_file.len - 2])
|
||||
}
|
||||
cleanup_files([file, temp_file])
|
||||
}
|
||||
mut r := new_repl()
|
||||
vexe := os.getenv('VEXE')
|
||||
|
@ -198,7 +184,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
|||
}
|
||||
if r.line.starts_with('print') {
|
||||
source_code := r.current_source_code(false) + '\n$r.line\n'
|
||||
os.write_file(file, source_code)
|
||||
os.write_file(file, source_code) or { panic(err) }
|
||||
s := os.exec('"$vexe" -repl run "$file"') or {
|
||||
rerror(err)
|
||||
return
|
||||
|
@ -208,7 +194,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
|||
mut temp_line := r.line
|
||||
mut temp_flag := false
|
||||
func_call := r.function_call(r.line)
|
||||
filter_line := r.line.replace(r.line.find_between("\'", "\'"), '').replace(r.line.find_between('"',
|
||||
filter_line := r.line.replace(r.line.find_between("'", "'"), '').replace(r.line.find_between('"',
|
||||
'"'), '')
|
||||
possible_statement_patterns := [
|
||||
'=',
|
||||
|
@ -268,7 +254,7 @@ fn run_repl(workdir string, vrepl_prefix string) {
|
|||
}
|
||||
temp_source_code = r.current_source_code(true) + '\n$temp_line\n'
|
||||
}
|
||||
os.write_file(temp_file, temp_source_code)
|
||||
os.write_file(temp_file, temp_source_code) or { panic(err) }
|
||||
s := os.exec('"$vexe" -repl run "$temp_file"') or {
|
||||
rerror(err)
|
||||
return
|
||||
|
@ -355,3 +341,18 @@ fn (mut r Repl) get_one_line(prompt string) ?string {
|
|||
rline := r.readline.read_line(prompt) or { return none }
|
||||
return rline
|
||||
}
|
||||
|
||||
fn cleanup_files(files []string) {
|
||||
for file in files {
|
||||
os.rm(file) or { }
|
||||
$if windows {
|
||||
os.rm(file[..file.len - 2] + '.exe') or { }
|
||||
$if msvc {
|
||||
os.rm(file[..file.len - 2] + '.ilk') or { }
|
||||
os.rm(file[..file.len - 2] + '.pdb') or { }
|
||||
}
|
||||
} $else {
|
||||
os.rm(file[..file.len - 2]) or { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import v.pref
|
|||
$if windows {
|
||||
$if tinyc {
|
||||
#flag -lAdvapi32
|
||||
|
||||
#flag -lUser32
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +20,16 @@ fn main() {
|
|||
fn setup_symlink(vexe string) {
|
||||
link_dir := '/usr/local/bin'
|
||||
if !os.exists(link_dir) {
|
||||
os.mkdir_all(link_dir)
|
||||
os.mkdir_all(link_dir) or { panic(err) }
|
||||
}
|
||||
mut link_path := link_dir + '/v'
|
||||
mut ret := os.exec('ln -sf $vexe $link_path') or {
|
||||
panic(err)
|
||||
}
|
||||
mut ret := os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||
if ret.exit_code == 0 {
|
||||
println('Symlink "$link_path" has been created')
|
||||
} else if os.system("uname -o | grep -q \'[A/a]ndroid\'") == 0 {
|
||||
} else if os.system("uname -o | grep -q '[A/a]ndroid'") == 0 {
|
||||
println('Failed to create symlink "$link_path". Trying again with Termux path for Android.')
|
||||
link_path = '/data/data/com.termux/files/usr/bin/v'
|
||||
ret = os.exec('ln -sf $vexe $link_path') or {
|
||||
panic(err)
|
||||
}
|
||||
ret = os.exec('ln -sf $vexe $link_path') or { panic(err) }
|
||||
if ret.exit_code == 0 {
|
||||
println('Symlink "$link_path" has been created')
|
||||
} else {
|
||||
|
@ -52,9 +49,9 @@ fn setup_symlink_windows(vexe string) {
|
|||
vsymlinkdir := os.join_path(vdir, '.bin')
|
||||
mut vsymlink := os.join_path(vsymlinkdir, 'v.exe')
|
||||
if !os.exists(vsymlinkdir) {
|
||||
os.mkdir_all(vsymlinkdir) // will panic if fails
|
||||
os.mkdir_all(vsymlinkdir) or { panic(err) } // will panic if fails
|
||||
} else {
|
||||
os.rm(vsymlink)
|
||||
os.rm(vsymlink) or { panic(err) }
|
||||
}
|
||||
// First, try to create a native symlink at .\.bin\v.exe
|
||||
os.symlink(vsymlink, vexe) or {
|
||||
|
@ -64,9 +61,9 @@ fn setup_symlink_windows(vexe string) {
|
|||
eprintln('Creating a batch file instead...')
|
||||
vsymlink = os.join_path(vsymlinkdir, 'v.bat')
|
||||
if os.exists(vsymlink) {
|
||||
os.rm(vsymlink)
|
||||
os.rm(vsymlink) or { panic(err) }
|
||||
}
|
||||
os.write_file(vsymlink, '@echo off\n$vexe %*')
|
||||
os.write_file(vsymlink, '@echo off\n$vexe %*') or { panic(err) }
|
||||
eprintln('$vsymlink file written.')
|
||||
}
|
||||
if !os.exists(vsymlink) {
|
||||
|
@ -83,9 +80,7 @@ fn setup_symlink_windows(vexe string) {
|
|||
// C.RegCloseKey(reg_sys_env_handle)
|
||||
// }
|
||||
// if the above succeeded, and we cannot get the value, it may simply be empty
|
||||
sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or {
|
||||
''
|
||||
}
|
||||
sys_env_path := get_reg_value(reg_sys_env_handle, 'Path') or { '' }
|
||||
current_sys_paths := sys_env_path.split(os.path_delimiter).map(it.trim('/$os.path_separator'))
|
||||
mut new_paths := [vsymlinkdir]
|
||||
for p in current_sys_paths {
|
||||
|
@ -171,8 +166,7 @@ fn set_reg_value(reg_key voidptr, key string, value string) ?bool {
|
|||
// letting them know that the system environment has changed and should be reloaded
|
||||
fn send_setting_change_msg(message_data string) ?bool {
|
||||
$if windows {
|
||||
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) ==
|
||||
0 {
|
||||
if C.SendMessageTimeout(os.hwnd_broadcast, os.wm_settingchange, 0, message_data.to_wide(), os.smto_abortifhung, 5000, 0) == 0 {
|
||||
return error('Could not broadcast WM_SETTINGCHANGE')
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -108,9 +108,9 @@ fn (app App) show_current_v_version() {
|
|||
fn (app App) backup(file string) {
|
||||
backup_file := '${file}_old.exe'
|
||||
if os.exists(backup_file) {
|
||||
os.rm(backup_file)
|
||||
os.rm(backup_file) or { panic(err) }
|
||||
}
|
||||
os.mv(file, backup_file)
|
||||
os.mv(file, backup_file) or { panic(err) }
|
||||
}
|
||||
|
||||
fn (app App) git_command(command string) {
|
||||
|
|
|
@ -7,7 +7,7 @@ fn main() {
|
|||
mut cm := vcache.new_cache_manager([])
|
||||
cpath := cm.basepath
|
||||
if os.exists(cpath) && os.is_dir(cpath) {
|
||||
os.rmdir_all(cpath)
|
||||
os.rmdir_all(cpath) or { }
|
||||
}
|
||||
println('V cache folder $cpath was wiped.')
|
||||
}
|
||||
|
|
|
@ -3,12 +3,14 @@ import io
|
|||
|
||||
fn main() {
|
||||
// Make a new connection
|
||||
mut conn := net.dial_tcp('google.com:80')?
|
||||
defer { conn.close() }
|
||||
mut conn := net.dial_tcp('google.com:80') ?
|
||||
defer {
|
||||
conn.close() or { }
|
||||
}
|
||||
// Simple http HEAD request for a file
|
||||
conn.write_str('HEAD /index.html HTTP/1.0\r\n\r\n')?
|
||||
conn.write_str('HEAD /index.html HTTP/1.0\r\n\r\n') ?
|
||||
// Read all the data that is waiting
|
||||
result := io.read_all(reader: conn)?
|
||||
result := io.read_all(reader: conn) ?
|
||||
// Cast to string and print result
|
||||
println(result.bytestr())
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ const (
|
|||
f_0 = 0.0
|
||||
)
|
||||
|
||||
/***************************** 3D Vector utility struct **********************/
|
||||
//**************************** 3D Vector utility struct *********************
|
||||
struct Vec {
|
||||
mut:
|
||||
x f64 = 0.0
|
||||
|
@ -44,46 +44,42 @@ mut:
|
|||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) + (b Vec) Vec{
|
||||
return Vec{ v.x + b.x , v.y + b.y, v.z + b.z }
|
||||
fn (v Vec) + (b Vec) Vec {
|
||||
return Vec{v.x + b.x, v.y + b.y, v.z + b.z}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) - (b Vec) Vec{
|
||||
return Vec{ v.x - b.x , v.y - b.y, v.z - b.z }
|
||||
fn (v Vec) - (b Vec) Vec {
|
||||
return Vec{v.x - b.x, v.y - b.y, v.z - b.z}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) * (b Vec) Vec{
|
||||
return Vec{ v.x * b.x , v.y * b.y, v.z * b.z }
|
||||
fn (v Vec) * (b Vec) Vec {
|
||||
return Vec{v.x * b.x, v.y * b.y, v.z * b.z}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) dot (b Vec) f64{
|
||||
fn (v Vec) dot(b Vec) f64 {
|
||||
return v.x * b.x + v.y * b.y + v.z * b.z
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) mult_s (b f64) Vec{
|
||||
return Vec{ v.x * b , v.y * b, v.z * b }
|
||||
fn (v Vec) mult_s(b f64) Vec {
|
||||
return Vec{v.x * b, v.y * b, v.z * b}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) cross (b Vec) Vec{
|
||||
return Vec{
|
||||
v.y * b.z - v.z * b.y,
|
||||
v.z * b.x - v.x * b.z,
|
||||
v.x * b.y - v.y * b.x
|
||||
}
|
||||
fn (v Vec) cross(b Vec) Vec {
|
||||
return Vec{v.y * b.z - v.z * b.y, v.z * b.x - v.x * b.z, v.x * b.y - v.y * b.x}
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (v Vec) norm () Vec {
|
||||
fn (v Vec) norm() Vec {
|
||||
tmp_norm := 1.0 / math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
|
||||
return Vec{ v.x * tmp_norm , v.y * tmp_norm, v.z * tmp_norm }
|
||||
return Vec{v.x * tmp_norm, v.y * tmp_norm, v.z * tmp_norm}
|
||||
}
|
||||
|
||||
/*********************************Image***************************************/
|
||||
//********************************Image**************************************
|
||||
struct Image {
|
||||
width int
|
||||
height int
|
||||
|
@ -93,9 +89,9 @@ struct Image {
|
|||
fn new_image(w int, h int) Image {
|
||||
vecsize := int(sizeof(Vec))
|
||||
return Image{
|
||||
width: w,
|
||||
height: h,
|
||||
data: &Vec(vcalloc(vecsize*w*h))
|
||||
width: w
|
||||
height: h
|
||||
data: &Vec(vcalloc(vecsize * w * h))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,19 +99,19 @@ fn new_image(w int, h int) Image {
|
|||
fn (image Image) save_as_ppm(file_name string) {
|
||||
npixels := image.width * image.height
|
||||
mut f_out := os.create(file_name) or { panic(err) }
|
||||
f_out.writeln('P3')
|
||||
f_out.writeln('${image.width} ${image.height}')
|
||||
f_out.writeln('255')
|
||||
for i in 0..npixels {
|
||||
c_r := to_int(unsafe{image.data[i]}.x)
|
||||
c_g := to_int(unsafe{image.data[i]}.y)
|
||||
c_b := to_int(unsafe{image.data[i]}.z)
|
||||
f_out.write_str('$c_r $c_g $c_b ')
|
||||
f_out.writeln('P3') or { panic(err) }
|
||||
f_out.writeln('$image.width $image.height') or { panic(err) }
|
||||
f_out.writeln('255') or { panic(err) }
|
||||
for i in 0 .. npixels {
|
||||
c_r := to_int(unsafe { image.data[i] }.x)
|
||||
c_g := to_int(unsafe { image.data[i] }.y)
|
||||
c_b := to_int(unsafe { image.data[i] }.z)
|
||||
f_out.write_str('$c_r $c_g $c_b ') or { panic(err) }
|
||||
}
|
||||
f_out.close()
|
||||
}
|
||||
|
||||
/*********************************** Ray *************************************/
|
||||
//********************************** Ray ************************************
|
||||
struct Ray {
|
||||
o Vec
|
||||
d Vec
|
||||
|
@ -128,7 +124,7 @@ enum Refl_t {
|
|||
refr
|
||||
}
|
||||
|
||||
/********************************* Sphere ************************************/
|
||||
//******************************** Sphere ***********************************
|
||||
struct Sphere {
|
||||
rad f64 = 0.0 // radius
|
||||
p Vec // position
|
||||
|
@ -137,7 +133,7 @@ struct Sphere {
|
|||
refl Refl_t // reflection type => [diffuse, specular, refractive]
|
||||
}
|
||||
|
||||
fn (sp Sphere) intersect (r Ray) f64 {
|
||||
fn (sp Sphere) intersect(r Ray) f64 {
|
||||
op := sp.p - r.o // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0
|
||||
b := op.dot(r.d)
|
||||
mut det := b * b - op.dot(op) + sp.rad * sp.rad
|
||||
|
@ -167,80 +163,179 @@ fn (sp Sphere) intersect (r Ray) f64 {
|
|||
* The sphere fileds are: Sphere{radius, position, emission, color, material}
|
||||
******************************************************************************/
|
||||
const (
|
||||
cen = Vec{50, 40.8, -860} // used by scene 1
|
||||
spheres = [
|
||||
[// scene 0 cornnel box
|
||||
Sphere{rad: 1e+5, p: Vec{ 1e+5 +1,40.8,81.6} , e: Vec{} , c: Vec{.75,.25,.25} , refl: .diff},//Left
|
||||
Sphere{rad: 1e+5, p: Vec{-1e+5 +99,40.8,81.6}, e: Vec{} , c: Vec{.25,.25,.75} , refl: .diff},//Rght
|
||||
Sphere{rad: 1e+5, p: Vec{50,40.8, 1e+5} , e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Back
|
||||
Sphere{rad: 1e+5, p: Vec{50,40.8,-1e+5 +170} , e: Vec{} , c: Vec{} , refl: .diff},//Frnt
|
||||
Sphere{rad: 1e+5, p: Vec{50, 1e+5, 81.6} , e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Botm
|
||||
Sphere{rad: 1e+5, p: Vec{50,-1e+5 +81.6,81.6}, e: Vec{} , c: Vec{.75,.75,.75} , refl: .diff},//Top
|
||||
Sphere{rad: 16.5, p: Vec{27,16.5,47} , e: Vec{} , c: Vec{1,1,1}.mult_s(.999) , refl: .spec},//Mirr
|
||||
Sphere{rad: 16.5, p: Vec{73,16.5,78} , e: Vec{} , c: Vec{1,1,1}.mult_s(.999) , refl: .refr},//Glas
|
||||
Sphere{rad: 600 , p: Vec{50,681.6-.27,81.6} , e: Vec{12,12,12}, c: Vec{}, refl: .diff} //Lite
|
||||
],
|
||||
|
||||
[// scene 1 sunset
|
||||
Sphere{rad: 1600, p: Vec{1.0,0.0,2.0}.mult_s(3000), e: Vec{1.0,.9,.8}.mult_s(1.2e+1*1.56*2) , c: Vec{} , refl: .diff}, // sun
|
||||
Sphere{rad: 1560, p: Vec{1,0,2}.mult_s(3500) , e: Vec{1.0,.5,.05}.mult_s(4.8e+1*1.56*2) , c: Vec{} , refl: .diff}, // horizon sun2
|
||||
Sphere{rad: 10000, p: cen+Vec{0,0,-200}, e: Vec{0.00063842, 0.02001478, 0.28923243}.mult_s(6e-2*8), c: Vec{.7,.7,1}.mult_s(.25), refl: .diff}, // sky
|
||||
|
||||
Sphere{rad: 100000, p: Vec{50, -100000, 0} , e: Vec{} , c: Vec{.3,.3,.3} , refl: .diff}, // grnd
|
||||
Sphere{rad: 110000, p: Vec{50, -110048.5, 0} , e: Vec{.9,.5,.05}.mult_s(4) , c: Vec{}, refl: .diff},// horizon brightener
|
||||
Sphere{rad: 4e+4 , p: Vec{50, -4e+4-30, -3000}, e: Vec{} , c: Vec{.2,.2,.2} , refl: .diff},// mountains
|
||||
|
||||
Sphere{rad: 26.5, p: Vec{22,26.5,42}, e: Vec{}, c: Vec{1,1,1}.mult_s(.596) , refl: .spec}, // white Mirr
|
||||
Sphere{rad: 13, p: Vec{75,13,82 }, e: Vec{}, c: Vec{.96,.96,.96}.mult_s(.96), refl: .refr},// Glas
|
||||
Sphere{rad: 22, p: Vec{87,22,24 }, e: Vec{}, c: Vec{.6,.6,.6}.mult_s(.696) , refl: .refr} // Glas2
|
||||
],
|
||||
|
||||
|
||||
[// scene 3 Psychedelic
|
||||
Sphere{rad: 150, p: Vec{50+75,28,62}, e: Vec{1,1,1}.mult_s(0e-3), c: Vec{1,.9,.8}.mult_s(.93), refl: .refr},
|
||||
Sphere{rad: 28 , p: Vec{50+5,-28,62}, e: Vec{1,1,1}.mult_s(1e+1), c: Vec{1,1,1}.mult_s(0) , refl: .diff},
|
||||
Sphere{rad: 300, p: Vec{50,28,62} , e: Vec{1,1,1}.mult_s(0e-3), c: Vec{1,1,1}.mult_s(.93) , refl: .spec}
|
||||
]
|
||||
|
||||
] // end of scene array
|
||||
|
||||
cen = Vec{50, 40.8, -860} // used by scene 1
|
||||
spheres = [
|
||||
[/* scene 0 cornnel box */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{1e+5 + 1, 40.8, 81.6}
|
||||
e: Vec{}
|
||||
c: Vec{.75, .25, .25}
|
||||
refl: .diff
|
||||
}, /* Left */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{-1e+5 + 99, 40.8, 81.6}
|
||||
e: Vec{}
|
||||
c: Vec{.25, .25, .75}
|
||||
refl: .diff
|
||||
}, /* Rght */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{50, 40.8, 1e+5}
|
||||
e: Vec{}
|
||||
c: Vec{.75, .75, .75}
|
||||
refl: .diff
|
||||
}, /* Back */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{50, 40.8, -1e+5 + 170}
|
||||
e: Vec{}
|
||||
c: Vec{}
|
||||
refl: .diff
|
||||
}, /* Frnt */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{50, 1e+5, 81.6}
|
||||
e: Vec{}
|
||||
c: Vec{.75, .75, .75}
|
||||
refl: .diff
|
||||
}, /* Botm */ Sphere{
|
||||
rad: 1e+5
|
||||
p: Vec{50, -1e+5 + 81.6, 81.6}
|
||||
e: Vec{}
|
||||
c: Vec{.75, .75, .75}
|
||||
refl: .diff
|
||||
}, /* Top */ Sphere{
|
||||
rad: 16.5
|
||||
p: Vec{27, 16.5, 47}
|
||||
e: Vec{}
|
||||
c: Vec{1, 1, 1}.mult_s(.999)
|
||||
refl: .spec
|
||||
}, /* Mirr */ Sphere{
|
||||
rad: 16.5
|
||||
p: Vec{73, 16.5, 78}
|
||||
e: Vec{}
|
||||
c: Vec{1, 1, 1}.mult_s(.999)
|
||||
refl: .refr
|
||||
}, /* Glas */ Sphere{
|
||||
rad: 600
|
||||
p: Vec{50, 681.6 - .27, 81.6}
|
||||
e: Vec{12, 12, 12}
|
||||
c: Vec{}
|
||||
refl: .diff
|
||||
} /* Lite */],
|
||||
[/* scene 1 sunset */ Sphere{
|
||||
rad: 1600
|
||||
p: Vec{1.0, 0.0, 2.0}.mult_s(3000)
|
||||
e: Vec{1.0, .9, .8}.mult_s(1.2e+1 * 1.56 * 2)
|
||||
c: Vec{}
|
||||
refl: .diff
|
||||
}, /* sun */ Sphere{
|
||||
rad: 1560
|
||||
p: Vec{1, 0, 2}.mult_s(3500)
|
||||
e: Vec{1.0, .5, .05}.mult_s(4.8e+1 * 1.56 * 2)
|
||||
c: Vec{}
|
||||
refl: .diff
|
||||
}, /* horizon sun2 */ Sphere{
|
||||
rad: 10000
|
||||
p: cen + Vec{0, 0, -200}
|
||||
e: Vec{0.00063842, 0.02001478, 0.28923243}.mult_s(6e-2 * 8)
|
||||
c: Vec{.7, .7, 1}.mult_s(.25)
|
||||
refl: .diff
|
||||
}, /* sky */ Sphere{
|
||||
rad: 100000
|
||||
p: Vec{50, -100000, 0}
|
||||
e: Vec{}
|
||||
c: Vec{.3, .3, .3}
|
||||
refl: .diff
|
||||
}, /* grnd */ Sphere{
|
||||
rad: 110000
|
||||
p: Vec{50, -110048.5, 0}
|
||||
e: Vec{.9, .5, .05}.mult_s(4)
|
||||
c: Vec{}
|
||||
refl: .diff
|
||||
}, /* horizon brightener */ Sphere{
|
||||
rad: 4e+4
|
||||
p: Vec{50, -4e+4 - 30, -3000}
|
||||
e: Vec{}
|
||||
c: Vec{.2, .2, .2}
|
||||
refl: .diff
|
||||
}, /* mountains */ Sphere{
|
||||
rad: 26.5
|
||||
p: Vec{22, 26.5, 42}
|
||||
e: Vec{}
|
||||
c: Vec{1, 1, 1}.mult_s(.596)
|
||||
refl: .spec
|
||||
}, /* white Mirr */ Sphere{
|
||||
rad: 13
|
||||
p: Vec{75, 13, 82}
|
||||
e: Vec{}
|
||||
c: Vec{.96, .96, .96}.mult_s(.96)
|
||||
refl: .refr
|
||||
}, /* Glas */ Sphere{
|
||||
rad: 22
|
||||
p: Vec{87, 22, 24}
|
||||
e: Vec{}
|
||||
c: Vec{.6, .6, .6}.mult_s(.696)
|
||||
refl: .refr
|
||||
} /* Glas2 */],
|
||||
[/* scene 3 Psychedelic */ Sphere{
|
||||
rad: 150
|
||||
p: Vec{50 + 75, 28, 62}
|
||||
e: Vec{1, 1, 1}.mult_s(0e-3)
|
||||
c: Vec{1, .9, .8}.mult_s(.93)
|
||||
refl: .refr
|
||||
}, Sphere{
|
||||
rad: 28
|
||||
p: Vec{50 + 5, -28, 62}
|
||||
e: Vec{1, 1, 1}.mult_s(1e+1)
|
||||
c: Vec{1, 1, 1}.mult_s(0)
|
||||
refl: .diff
|
||||
}, Sphere{
|
||||
rad: 300
|
||||
p: Vec{50, 28, 62}
|
||||
e: Vec{1, 1, 1}.mult_s(0e-3)
|
||||
c: Vec{1, 1, 1}.mult_s(.93)
|
||||
refl: .spec
|
||||
}],
|
||||
] // end of scene array
|
||||
)
|
||||
|
||||
/*********************************** Utilities *******************************/
|
||||
//********************************** Utilities ******************************
|
||||
[inline]
|
||||
fn clamp(x f64) f64 {
|
||||
if x < 0 { return 0 }
|
||||
if x > 1 { return 1 }
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
if x > 1 {
|
||||
return 1
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn to_int(x f64) int {
|
||||
p := math.pow(clamp(x), 1.0/2.2)
|
||||
return int(p*255.0+0.5)
|
||||
p := math.pow(clamp(x), 1.0 / 2.2)
|
||||
return int(p * 255.0 + 0.5)
|
||||
}
|
||||
|
||||
fn intersect(r Ray, spheres &Sphere, nspheres int) (bool, f64, int){
|
||||
fn intersect(r Ray, spheres &Sphere, nspheres int) (bool, f64, int) {
|
||||
mut d := 0.0
|
||||
mut t := inf
|
||||
mut id := 0
|
||||
for i:=nspheres-1; i >= 0; i-- {
|
||||
d = unsafe{spheres[i]}.intersect(r)
|
||||
for i := nspheres - 1; i >= 0; i-- {
|
||||
d = unsafe { spheres[i] }.intersect(r)
|
||||
if d > 0 && d < t {
|
||||
t = d
|
||||
id = i
|
||||
}
|
||||
}
|
||||
return (t < inf) , t, id
|
||||
return (t < inf), t, id
|
||||
}
|
||||
|
||||
// some casual random function, try to avoid the 0
|
||||
fn rand_f64() f64 {
|
||||
x := rand.u32() & 0x3FFF_FFFF
|
||||
return f64(x)/f64(0x3FFF_FFFF)
|
||||
return f64(x) / f64(0x3FFF_FFFF)
|
||||
}
|
||||
|
||||
const(
|
||||
const (
|
||||
cache_len = 65536 // the 2*pi angle will be splitted in 65536 part
|
||||
cache_mask = cache_len - 1 // mask to speed-up the module process
|
||||
)
|
||||
|
@ -254,7 +349,7 @@ mut:
|
|||
fn new_tabs() Cache {
|
||||
mut c := Cache{}
|
||||
inv_len := 1.0 / f64(cache_len)
|
||||
for i in 0..cache_len {
|
||||
for i in 0 .. cache_len {
|
||||
x := f64(i) * math.pi * 2.0 * inv_len
|
||||
c.sin_tab[i] = math.sin(x)
|
||||
c.cos_tab[i] = math.cos(x)
|
||||
|
@ -262,12 +357,12 @@ fn new_tabs() Cache {
|
|||
return c
|
||||
}
|
||||
|
||||
/************* Cache for sin/cos speed-up table and scene selector ***********/
|
||||
//************ Cache for sin/cos speed-up table and scene selector **********
|
||||
const (
|
||||
tabs = new_tabs()
|
||||
)
|
||||
|
||||
/******************* main function for the radiance calculation **************/
|
||||
//****************** main function for the radiance calculation *************
|
||||
fn radiance(r Ray, depthi int, scene_id int) Vec {
|
||||
if depthi > 1024 {
|
||||
eprintln('depthi: $depthi')
|
||||
|
@ -279,12 +374,15 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
|||
mut res := false // result of intersect
|
||||
|
||||
v_1 := 1.0
|
||||
//v_2 := f64(2.0)
|
||||
// v_2 := f64(2.0)
|
||||
|
||||
scene := spheres[scene_id]
|
||||
//res, t, id = intersect(r, id, tb.scene)
|
||||
// res, t, id = intersect(r, id, tb.scene)
|
||||
res, t, id = intersect(r, scene.data, scene.len)
|
||||
if !res { return Vec{} } //if miss, return black
|
||||
if !res {
|
||||
return Vec{}
|
||||
}
|
||||
// if miss, return black
|
||||
|
||||
obj := scene[id] // the hit object
|
||||
|
||||
|
@ -308,15 +406,15 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
|||
depth++
|
||||
if depth > 5 {
|
||||
if rand_f64() < p {
|
||||
f = f.mult_s(f64(1.0)/p)
|
||||
f = f.mult_s(f64(1.0) / p)
|
||||
} else {
|
||||
return obj.e //R.R.
|
||||
return obj.e // R.R.
|
||||
}
|
||||
}
|
||||
|
||||
if obj.refl == .diff { // Ideal DIFFUSE reflection
|
||||
// **Full Precision**
|
||||
//r1 := f64(2.0 * math.pi) * rand_f64()
|
||||
// r1 := f64(2.0 * math.pi) * rand_f64()
|
||||
|
||||
// tabbed speed-up
|
||||
r1 := rand.u32() & cache_mask
|
||||
|
@ -326,25 +424,22 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
|||
|
||||
w := nl
|
||||
|
||||
mut u := if math.abs(w.x) > f64(0.1) {
|
||||
Vec{0, 1, 0}
|
||||
} else {
|
||||
Vec{1, 0, 0}
|
||||
}
|
||||
mut u := if math.abs(w.x) > f64(0.1) { Vec{0, 1, 0} } else { Vec{1, 0, 0} }
|
||||
u = u.cross(w).norm()
|
||||
|
||||
v := w.cross(u)
|
||||
|
||||
// **Full Precision**
|
||||
//d := (u.mult_s(math.cos(r1) * r2s) + v.mult_s(math.sin(r1) * r2s) + w.mult_s(1.0 - r2)).norm()
|
||||
// d := (u.mult_s(math.cos(r1) * r2s) + v.mult_s(math.sin(r1) * r2s) + w.mult_s(1.0 - r2)).norm()
|
||||
|
||||
// tabbed speed-up
|
||||
d := (u.mult_s(tabs.cos_tab[r1] * r2s) + v.mult_s(tabs.sin_tab[r1] * r2s) + w.mult_s(math.sqrt(f64(1.0) - r2))).norm()
|
||||
d := (u.mult_s(tabs.cos_tab[r1] * r2s) + v.mult_s(tabs.sin_tab[r1] * r2s) +
|
||||
w.mult_s(math.sqrt(f64(1.0) - r2))).norm()
|
||||
|
||||
return obj.e + f * radiance(Ray{x, d}, depth, scene_id)
|
||||
} else {
|
||||
if obj.refl == .spec { // Ideal SPECULAR reflection
|
||||
return obj.e + f * radiance(Ray{x, r.d - n.mult_s(2.0 * n.dot(r.d)) }, depth, scene_id)
|
||||
return obj.e + f * radiance(Ray{x, r.d - n.mult_s(2.0 * n.dot(r.d))}, depth, scene_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,18 +474,16 @@ fn radiance(r Ray, depthi int, scene_id int) Vec {
|
|||
mut tmp := Vec{}
|
||||
if depth > 2 {
|
||||
// Russian roulette
|
||||
tmp = if rand_f64() < pp {
|
||||
radiance(refl_ray, depth, scene_id).mult_s(rp)
|
||||
tmp = if rand_f64() < pp { radiance(refl_ray, depth, scene_id).mult_s(rp) } else { radiance(Ray{x, tdir},
|
||||
depth, scene_id).mult_s(tp) }
|
||||
} else {
|
||||
radiance(Ray{x, tdir}, depth, scene_id).mult_s(tp)
|
||||
}
|
||||
} else {
|
||||
tmp = (radiance(refl_ray, depth, scene_id).mult_s(re)) + (radiance( Ray{x, tdir}, depth, scene_id).mult_s(tr))
|
||||
tmp = (radiance(refl_ray, depth, scene_id).mult_s(re)) +
|
||||
(radiance(Ray{x, tdir}, depth, scene_id).mult_s(tr))
|
||||
}
|
||||
return obj.e + (f * tmp)
|
||||
}
|
||||
|
||||
/************************ beam scan routine **********************************/
|
||||
//*********************** beam scan routine *********************************
|
||||
fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
||||
image := new_image(w, h)
|
||||
|
||||
|
@ -400,7 +493,7 @@ fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
|||
samps1 := f64(1.0 / f64(samps))
|
||||
|
||||
cam := Ray{Vec{50, 52, 295.6}, Vec{0, -0.042612, -1}.norm()} // cam position, direction
|
||||
cx := Vec{ f64(w) * 0.5135 / f64(h), 0, 0}
|
||||
cx := Vec{f64(w) * 0.5135 / f64(h), 0, 0}
|
||||
cy := cx.cross(cam.d).norm().mult_s(0.5135)
|
||||
mut r := Vec{}
|
||||
|
||||
|
@ -409,28 +502,28 @@ fn ray_trace(w int, h int, samps int, file_name string, scene_id int) Image {
|
|||
v_2 := f64(2.0)
|
||||
|
||||
// OpenMP injection point! #pragma omp parallel for schedule(dynamic, 1) shared(c)
|
||||
for y:=0; y < h; y++ {
|
||||
eprint("\rRendering (${samps * 4} spp) ${(100.0 * f64(y)) / (f64(h) - 1.0):5.2f}%")
|
||||
for x in 0..w {
|
||||
|
||||
for y := 0; y < h; y++ {
|
||||
eprint('\rRendering (${samps * 4} spp) ${(100.0 * f64(y)) / (f64(h) - 1.0):5.2f}%')
|
||||
for x in 0 .. w {
|
||||
i := (h - y - 1) * w + x
|
||||
mut ivec := unsafe{&image.data[i]}
|
||||
mut ivec := unsafe { &image.data[i] }
|
||||
// we use sx and sy to perform a square subsampling of 4 samples
|
||||
for sy := 0; sy < 2; sy ++ {
|
||||
for sx := 0; sx < 2; sx ++ {
|
||||
r = Vec{0,0,0}
|
||||
for _ in 0..samps {
|
||||
for sy := 0; sy < 2; sy++ {
|
||||
for sx := 0; sx < 2; sx++ {
|
||||
r = Vec{0, 0, 0}
|
||||
for _ in 0 .. samps {
|
||||
r1 := v_2 * rand_f64()
|
||||
dx := if r1 < v_1 { math.sqrt(r1) - v_1 } else { v_1 - math.sqrt(v_2 - r1) }
|
||||
|
||||
r2 := v_2 * rand_f64()
|
||||
dy := if r2 < v_1 { math.sqrt(r2) - v_1 } else { v_1 - math.sqrt(v_2 - r2) }
|
||||
|
||||
d := cx.mult_s( ( (f64(sx) + 0.5 + dx)*0.5 + f64(x))*w1 - .5) +
|
||||
cy.mult_s( ( (f64(sy) + 0.5 + dy)*0.5 + f64(y))*h1 - .5) + cam.d
|
||||
r = r + radiance(Ray{cam.o+d.mult_s(140.0), d.norm()}, 0, scene_id).mult_s(samps1)
|
||||
d := cx.mult_s(((f64(sx) + 0.5 + dx) * 0.5 + f64(x)) * w1 - .5) +
|
||||
cy.mult_s(((f64(sy) + 0.5 + dy) * 0.5 + f64(y)) * h1 - .5) + cam.d
|
||||
r = r + radiance(Ray{cam.o +
|
||||
d.mult_s(140.0), d.norm()}, 0, scene_id).mult_s(samps1)
|
||||
}
|
||||
tmp_vec := Vec{clamp(r.x),clamp(r.y),clamp(r.z)}.mult_s(.25)
|
||||
tmp_vec := Vec{clamp(r.x), clamp(r.y), clamp(r.z)}.mult_s(.25)
|
||||
(*ivec) = *ivec + tmp_vec
|
||||
}
|
||||
}
|
||||
|
@ -465,20 +558,18 @@ fn main() {
|
|||
if os.args.len == 6 {
|
||||
height = os.args[5].int()
|
||||
}
|
||||
|
||||
// change the seed for a different result
|
||||
rand.seed([u32(2020), 0])
|
||||
|
||||
t1:=time.ticks()
|
||||
t1 := time.ticks()
|
||||
|
||||
image := ray_trace(width, height, samples, file_name, scene_id)
|
||||
t2:=time.ticks()
|
||||
t2 := time.ticks()
|
||||
|
||||
eprintln('\nRendering finished. Took: ${(t2 - t1):5}ms')
|
||||
|
||||
eprintln('\nRendering finished. Took: ${(t2-t1):5}ms')
|
||||
image.save_as_ppm(file_name)
|
||||
t3 := time.ticks()
|
||||
|
||||
image.save_as_ppm( file_name )
|
||||
t3:=time.ticks()
|
||||
|
||||
eprintln('Image saved as [${file_name}]. Took: ${(t3-t2):5}ms')
|
||||
eprintln('Image saved as [$file_name]. Took: ${(t3 - t2):5}ms')
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ import term.ui as tui
|
|||
|
||||
const (
|
||||
colors = [
|
||||
tui.Color{33, 150, 243}
|
||||
tui.Color{0, 150, 136}
|
||||
tui.Color{205, 220, 57}
|
||||
tui.Color{255, 152, 0}
|
||||
tui.Color{244, 67, 54}
|
||||
tui.Color{156, 39, 176}
|
||||
tui.Color{33, 150, 243},
|
||||
tui.Color{0, 150, 136},
|
||||
tui.Color{205, 220, 57},
|
||||
tui.Color{255, 152, 0},
|
||||
tui.Color{244, 67, 54},
|
||||
tui.Color{156, 39, 176},
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -66,27 +66,33 @@ fn event(e &tui.Event, x voidptr) {
|
|||
}
|
||||
.space, .enter {
|
||||
app.color_idx++
|
||||
if app.color_idx == colors.len { app.color_idx = 0 }
|
||||
app.color = colors[app.color_idx]
|
||||
} else {}
|
||||
if app.color_idx == colors.len {
|
||||
app.color_idx = 0
|
||||
}
|
||||
} .mouse_move, .mouse_drag, .mouse_down {
|
||||
app.points << Point{ e.x, e.y }
|
||||
} .mouse_scroll {
|
||||
app.color = colors[app.color_idx]
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
.mouse_move, .mouse_drag, .mouse_down {
|
||||
app.points << Point{e.x, e.y}
|
||||
}
|
||||
.mouse_scroll {
|
||||
d := if e.direction == .up { 0.1 } else { -0.1 }
|
||||
app.cut_rate += d
|
||||
if app.cut_rate < 1 { app.cut_rate = 1 }
|
||||
} else {}
|
||||
if app.cut_rate < 1 {
|
||||
app.cut_rate = 1
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
||||
mut app := &App{}
|
||||
app.tui = tui.init(
|
||||
user_data: app,
|
||||
frame_fn: frame,
|
||||
event_fn: event,
|
||||
|
||||
user_data: app
|
||||
frame_fn: frame
|
||||
event_fn: event
|
||||
hide_cursor: true
|
||||
)
|
||||
|
||||
app.tui.run()
|
||||
app.tui.run() ?
|
||||
|
|
|
@ -11,29 +11,35 @@ fn event(e &tui.Event, x voidptr) {
|
|||
app.tui.set_cursor_position(0, 0)
|
||||
app.tui.write('V term.input event viewer (press `esc` to exit)\n\n')
|
||||
app.tui.write('$e')
|
||||
app.tui.write('\n\nRaw event bytes: "${e.utf8.bytes().hex()}" = ${e.utf8.bytes()}')
|
||||
app.tui.write('\n\nRaw event bytes: "$e.utf8.bytes().hex()" = $e.utf8.bytes()')
|
||||
if e.modifiers != 0 {
|
||||
app.tui.write('\nModifiers: $e.modifiers = ')
|
||||
if e.modifiers & tui.ctrl != 0 { app.tui.write('ctrl. ') }
|
||||
if e.modifiers & tui.shift != 0 { app.tui.write('shift ') }
|
||||
if e.modifiers & tui.alt != 0 { app.tui.write('alt. ') }
|
||||
if e.modifiers & tui.ctrl != 0 {
|
||||
app.tui.write('ctrl. ')
|
||||
}
|
||||
if e.modifiers & tui.shift != 0 {
|
||||
app.tui.write('shift ')
|
||||
}
|
||||
if e.modifiers & tui.alt != 0 {
|
||||
app.tui.write('alt. ')
|
||||
}
|
||||
}
|
||||
app.tui.flush()
|
||||
|
||||
if e.typ == .key_down && e.code == .escape { exit(0) }
|
||||
if e.typ == .key_down && e.code == .escape {
|
||||
exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
mut app := &App{}
|
||||
app.tui = tui.init(
|
||||
user_data: app,
|
||||
user_data: app
|
||||
event_fn: event
|
||||
|
||||
window_title: 'V term.ui event viewer'
|
||||
hide_cursor: true
|
||||
capture_events: true
|
||||
frame_rate: 60
|
||||
use_alternate_buffer: false
|
||||
)
|
||||
|
||||
println('V term.ui event viewer (press `esc` to exit)\n\n')
|
||||
app.tui.run()
|
||||
app.tui.run() ?
|
||||
|
|
|
@ -35,10 +35,10 @@ fn (mut a App) init() {
|
|||
a.width = w
|
||||
a.height = h
|
||||
term.erase_del_clear()
|
||||
term.set_cursor_position({
|
||||
term.set_cursor_position(
|
||||
x: 0
|
||||
y: 0
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn (mut a App) start_game() {
|
||||
|
@ -66,10 +66,10 @@ fn (mut a App) quit() {
|
|||
a.game.quit()
|
||||
return
|
||||
}
|
||||
term.set_cursor_position({
|
||||
term.set_cursor_position(
|
||||
x: 0
|
||||
y: 0
|
||||
})
|
||||
)
|
||||
exit(0)
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,7 @@ fn event(e &ui.Event, x voidptr) {
|
|||
|
||||
// main
|
||||
mut app := &App{}
|
||||
app.tui = ui.init({
|
||||
app.tui = ui.init(
|
||||
user_data: app
|
||||
init_fn: init
|
||||
frame_fn: frame
|
||||
|
@ -492,5 +492,5 @@ app.tui = ui.init({
|
|||
capture_events: true
|
||||
hide_cursor: true
|
||||
frame_rate: 60
|
||||
})
|
||||
app.tui.run()
|
||||
)
|
||||
app.tui.run() ?
|
||||
|
|
|
@ -43,20 +43,28 @@ fn event(e &tui.Event, x voidptr) {
|
|||
.mouse_drag {
|
||||
app.cur_rect.x2 = e.x
|
||||
app.cur_rect.y2 = e.y
|
||||
} .mouse_up {
|
||||
}
|
||||
.mouse_up {
|
||||
app.rects << app.cur_rect
|
||||
app.is_drag = false
|
||||
} .key_down {
|
||||
if e.code == .c { app.rects.clear() }
|
||||
else if e.code == .escape { exit(0) }
|
||||
} else {}
|
||||
}
|
||||
.key_down {
|
||||
if e.code == .c {
|
||||
app.rects.clear()
|
||||
} else if e.code == .escape {
|
||||
exit(0)
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
app.redraw = true
|
||||
}
|
||||
|
||||
fn frame(x voidptr) {
|
||||
mut app := &App(x)
|
||||
if !app.redraw { return }
|
||||
if !app.redraw {
|
||||
return
|
||||
}
|
||||
|
||||
app.tui.clear()
|
||||
|
||||
|
@ -76,15 +84,12 @@ fn frame(x voidptr) {
|
|||
app.redraw = false
|
||||
}
|
||||
|
||||
|
||||
mut app := &App{}
|
||||
app.tui = tui.init(
|
||||
user_data: app,
|
||||
event_fn: event,
|
||||
user_data: app
|
||||
event_fn: event
|
||||
frame_fn: frame
|
||||
|
||||
hide_cursor: true
|
||||
frame_rate: 60
|
||||
)
|
||||
|
||||
app.tui.run()
|
||||
app.tui.run() ?
|
||||
|
|
|
@ -3,73 +3,73 @@
|
|||
// that can be found in the LICENSE file.
|
||||
module main
|
||||
|
||||
import term.ui as tui
|
||||
import term.ui
|
||||
|
||||
// The color palette, taken from Google's Material design
|
||||
const (
|
||||
colors = [
|
||||
[
|
||||
tui.Color{239, 154, 154},
|
||||
tui.Color{244, 143, 177},
|
||||
tui.Color{206, 147, 216},
|
||||
tui.Color{179, 157, 219},
|
||||
tui.Color{159, 168, 218},
|
||||
tui.Color{144, 202, 249},
|
||||
tui.Color{129, 212, 250},
|
||||
tui.Color{128, 222, 234},
|
||||
tui.Color{128, 203, 196},
|
||||
tui.Color{165, 214, 167},
|
||||
tui.Color{197, 225, 165},
|
||||
tui.Color{230, 238, 156},
|
||||
tui.Color{255, 245, 157},
|
||||
tui.Color{255, 224, 130},
|
||||
tui.Color{255, 204, 128},
|
||||
tui.Color{255, 171, 145},
|
||||
tui.Color{188, 170, 164},
|
||||
tui.Color{238, 238, 238},
|
||||
tui.Color{176, 190, 197},
|
||||
ui.Color{239, 154, 154},
|
||||
ui.Color{244, 143, 177},
|
||||
ui.Color{206, 147, 216},
|
||||
ui.Color{179, 157, 219},
|
||||
ui.Color{159, 168, 218},
|
||||
ui.Color{144, 202, 249},
|
||||
ui.Color{129, 212, 250},
|
||||
ui.Color{128, 222, 234},
|
||||
ui.Color{128, 203, 196},
|
||||
ui.Color{165, 214, 167},
|
||||
ui.Color{197, 225, 165},
|
||||
ui.Color{230, 238, 156},
|
||||
ui.Color{255, 245, 157},
|
||||
ui.Color{255, 224, 130},
|
||||
ui.Color{255, 204, 128},
|
||||
ui.Color{255, 171, 145},
|
||||
ui.Color{188, 170, 164},
|
||||
ui.Color{238, 238, 238},
|
||||
ui.Color{176, 190, 197},
|
||||
],
|
||||
[
|
||||
tui.Color{244, 67, 54},
|
||||
tui.Color{233, 30, 99},
|
||||
tui.Color{156, 39, 176},
|
||||
tui.Color{103, 58, 183},
|
||||
tui.Color{63, 81, 181},
|
||||
tui.Color{33, 150, 243},
|
||||
tui.Color{3, 169, 244},
|
||||
tui.Color{0, 188, 212},
|
||||
tui.Color{0, 150, 136},
|
||||
tui.Color{76, 175, 80},
|
||||
tui.Color{139, 195, 74},
|
||||
tui.Color{205, 220, 57},
|
||||
tui.Color{255, 235, 59},
|
||||
tui.Color{255, 193, 7},
|
||||
tui.Color{255, 152, 0},
|
||||
tui.Color{255, 87, 34},
|
||||
tui.Color{121, 85, 72},
|
||||
tui.Color{120, 120, 120},
|
||||
tui.Color{96, 125, 139},
|
||||
ui.Color{244, 67, 54},
|
||||
ui.Color{233, 30, 99},
|
||||
ui.Color{156, 39, 176},
|
||||
ui.Color{103, 58, 183},
|
||||
ui.Color{63, 81, 181},
|
||||
ui.Color{33, 150, 243},
|
||||
ui.Color{3, 169, 244},
|
||||
ui.Color{0, 188, 212},
|
||||
ui.Color{0, 150, 136},
|
||||
ui.Color{76, 175, 80},
|
||||
ui.Color{139, 195, 74},
|
||||
ui.Color{205, 220, 57},
|
||||
ui.Color{255, 235, 59},
|
||||
ui.Color{255, 193, 7},
|
||||
ui.Color{255, 152, 0},
|
||||
ui.Color{255, 87, 34},
|
||||
ui.Color{121, 85, 72},
|
||||
ui.Color{120, 120, 120},
|
||||
ui.Color{96, 125, 139},
|
||||
],
|
||||
[
|
||||
tui.Color{198, 40, 40},
|
||||
tui.Color{173, 20, 87},
|
||||
tui.Color{106, 27, 154},
|
||||
tui.Color{69, 39, 160},
|
||||
tui.Color{40, 53, 147},
|
||||
tui.Color{21, 101, 192},
|
||||
tui.Color{2, 119, 189},
|
||||
tui.Color{0, 131, 143},
|
||||
tui.Color{0, 105, 92},
|
||||
tui.Color{46, 125, 50},
|
||||
tui.Color{85, 139, 47},
|
||||
tui.Color{158, 157, 36},
|
||||
tui.Color{249, 168, 37},
|
||||
tui.Color{255, 143, 0},
|
||||
tui.Color{239, 108, 0},
|
||||
tui.Color{216, 67, 21},
|
||||
tui.Color{78, 52, 46},
|
||||
tui.Color{33, 33, 33},
|
||||
tui.Color{55, 71, 79},
|
||||
ui.Color{198, 40, 40},
|
||||
ui.Color{173, 20, 87},
|
||||
ui.Color{106, 27, 154},
|
||||
ui.Color{69, 39, 160},
|
||||
ui.Color{40, 53, 147},
|
||||
ui.Color{21, 101, 192},
|
||||
ui.Color{2, 119, 189},
|
||||
ui.Color{0, 131, 143},
|
||||
ui.Color{0, 105, 92},
|
||||
ui.Color{46, 125, 50},
|
||||
ui.Color{85, 139, 47},
|
||||
ui.Color{158, 157, 36},
|
||||
ui.Color{249, 168, 37},
|
||||
ui.Color{255, 143, 0},
|
||||
ui.Color{239, 108, 0},
|
||||
ui.Color{216, 67, 21},
|
||||
ui.Color{78, 52, 46},
|
||||
ui.Color{33, 33, 33},
|
||||
ui.Color{55, 71, 79},
|
||||
],
|
||||
]
|
||||
)
|
||||
|
@ -90,17 +90,17 @@ const (
|
|||
|
||||
struct App {
|
||||
mut:
|
||||
tui &tui.Context = 0
|
||||
ui &ui.Context = 0
|
||||
header_text []string
|
||||
mouse_pos Point
|
||||
msg string
|
||||
msg_hide_tick int
|
||||
primary_color tui.Color = colors[1][6]
|
||||
secondary_color tui.Color = colors[1][9]
|
||||
primary_color ui.Color = colors[1][6]
|
||||
secondary_color ui.Color = colors[1][9]
|
||||
primary_color_idx int = 25
|
||||
secondary_color_idx int = 28
|
||||
bg_color tui.Color = tui.Color{0, 0, 0}
|
||||
drawing [][]tui.Color = [][]tui.Color{len: h, init: []tui.Color{len: w}}
|
||||
bg_color ui.Color = ui.Color{0, 0, 0}
|
||||
drawing [][]ui.Color = [][]ui.Color{len: h, init: []ui.Color{len: w}}
|
||||
size int = 1
|
||||
should_redraw bool = true
|
||||
is_dragging bool
|
||||
|
@ -114,24 +114,24 @@ mut:
|
|||
|
||||
fn main() {
|
||||
mut app := &App{}
|
||||
app.tui = tui.init({
|
||||
app.ui = ui.init(
|
||||
user_data: app
|
||||
frame_fn: frame
|
||||
event_fn: event
|
||||
frame_rate: frame_rate
|
||||
hide_cursor: true
|
||||
window_title: 'V terminal pixelart drawing app'
|
||||
})
|
||||
)
|
||||
app.mouse_pos.x = 40
|
||||
app.mouse_pos.y = 15
|
||||
app.tui.clear()
|
||||
app.tui.run()
|
||||
app.ui.clear()
|
||||
app.ui.run() ?
|
||||
}
|
||||
|
||||
fn frame(x voidptr) {
|
||||
mut app := &App(x)
|
||||
mut redraw := app.should_redraw
|
||||
if app.msg != '' && app.tui.frame_count >= app.msg_hide_tick {
|
||||
if app.msg != '' && app.ui.frame_count >= app.msg_hide_tick {
|
||||
app.msg = ''
|
||||
redraw = true
|
||||
}
|
||||
|
@ -141,12 +141,12 @@ fn frame(x voidptr) {
|
|||
}
|
||||
}
|
||||
|
||||
fn event(event &tui.Event, x voidptr) {
|
||||
fn event(event &ui.Event, x voidptr) {
|
||||
mut app := &App(x)
|
||||
match event.typ {
|
||||
.mouse_down {
|
||||
app.is_dragging = true
|
||||
if app.tui.window_height - event.y < 5 {
|
||||
if app.ui.window_height - event.y < 5 {
|
||||
app.footer_click(event)
|
||||
} else {
|
||||
app.paint(event)
|
||||
|
@ -174,8 +174,8 @@ fn event(event &tui.Event, x voidptr) {
|
|||
y: event.y
|
||||
}
|
||||
d := event.direction == .down
|
||||
if event.modifiers & tui.ctrl != 0 {
|
||||
p := event.modifiers & tui.shift == 0
|
||||
if event.modifiers & ui.ctrl != 0 {
|
||||
p := event.modifiers & ui.shift == 0
|
||||
c := if d {
|
||||
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
||||
} else {
|
||||
|
@ -183,53 +183,72 @@ fn event(event &tui.Event, x voidptr) {
|
|||
}
|
||||
app.select_color(p, c)
|
||||
} else {
|
||||
if d { app.inc_size() } else { app.dec_size() }
|
||||
if d {
|
||||
app.inc_size()
|
||||
} else {
|
||||
app.dec_size()
|
||||
}
|
||||
}
|
||||
}
|
||||
.key_down {
|
||||
match event.code {
|
||||
.f1, ._1 {
|
||||
oevent := *event
|
||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.left, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
||||
nevent := ui.Event{
|
||||
...oevent
|
||||
button: ui.MouseButton.left
|
||||
x: app.mouse_pos.x
|
||||
y: app.mouse_pos.y
|
||||
}
|
||||
app.paint(nevent)
|
||||
}
|
||||
.f2, ._2 {
|
||||
oevent := *event
|
||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.right, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
||||
nevent := ui.Event{
|
||||
...oevent
|
||||
button: ui.MouseButton.right
|
||||
x: app.mouse_pos.x
|
||||
y: app.mouse_pos.y
|
||||
}
|
||||
app.paint(nevent)
|
||||
}
|
||||
.space {
|
||||
oevent := *event
|
||||
nevent := tui.Event{ ...oevent, button: tui.MouseButton.middle, x: app.mouse_pos.x , y: app.mouse_pos.y }
|
||||
nevent := ui.Event{
|
||||
...oevent
|
||||
button: ui.MouseButton.middle
|
||||
x: app.mouse_pos.x
|
||||
y: app.mouse_pos.y
|
||||
}
|
||||
app.paint(nevent)
|
||||
}
|
||||
.j, .down {
|
||||
if event.modifiers & tui.shift != 0 {
|
||||
if event.modifiers & ui.shift != 0 {
|
||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||
}
|
||||
app.mouse_pos.y++
|
||||
}
|
||||
.k, .up {
|
||||
if event.modifiers & tui.shift != 0 {
|
||||
if event.modifiers & ui.shift != 0 {
|
||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||
}
|
||||
app.mouse_pos.y--
|
||||
}
|
||||
.h, .left {
|
||||
if event.modifiers & tui.shift != 0 {
|
||||
if event.modifiers & ui.shift != 0 {
|
||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||
}
|
||||
app.mouse_pos.x -= 2
|
||||
}
|
||||
.l, .right {
|
||||
if event.modifiers & tui.shift != 0 {
|
||||
if event.modifiers & ui.shift != 0 {
|
||||
app.set_pixel((1 + app.mouse_pos.x) / 2, app.mouse_pos.y, app.primary_color)
|
||||
}
|
||||
app.mouse_pos.x += 2
|
||||
}
|
||||
.t {
|
||||
p := event.modifiers & tui.alt == 0
|
||||
c := if event.modifiers & tui.shift != 0 {
|
||||
p := event.modifiers & ui.alt == 0
|
||||
c := if event.modifiers & ui.shift != 0 {
|
||||
if p { app.primary_color_idx - 19 } else { app.secondary_color_idx - 19 }
|
||||
} else {
|
||||
if p { app.primary_color_idx + 19 } else { app.secondary_color_idx + 19 }
|
||||
|
@ -237,8 +256,8 @@ fn event(event &tui.Event, x voidptr) {
|
|||
app.select_color(p, c)
|
||||
}
|
||||
.r {
|
||||
p := event.modifiers & tui.alt == 0
|
||||
c := if event.modifiers & tui.shift != 0 {
|
||||
p := event.modifiers & ui.alt == 0
|
||||
c := if event.modifiers & ui.shift != 0 {
|
||||
if p { app.primary_color_idx - 1 } else { app.secondary_color_idx - 1 }
|
||||
} else {
|
||||
if p { app.primary_color_idx + 1 } else { app.secondary_color_idx + 1 }
|
||||
|
@ -252,7 +271,7 @@ fn event(event &tui.Event, x voidptr) {
|
|||
app.dec_size()
|
||||
}
|
||||
.c {
|
||||
app.drawing = [][]tui.Color{len: h, init: []tui.Color{len: w}}
|
||||
app.drawing = [][]ui.Color{len: h, init: []ui.Color{len: w}}
|
||||
}
|
||||
.q, .escape {
|
||||
app.render(true)
|
||||
|
@ -267,14 +286,14 @@ fn event(event &tui.Event, x voidptr) {
|
|||
}
|
||||
|
||||
fn (mut app App) render(paint_only bool) {
|
||||
app.tui.clear()
|
||||
app.ui.clear()
|
||||
app.draw_header()
|
||||
app.draw_content()
|
||||
if !paint_only {
|
||||
app.draw_footer()
|
||||
app.draw_cursor()
|
||||
}
|
||||
app.tui.flush()
|
||||
app.ui.flush()
|
||||
}
|
||||
|
||||
fn (mut app App) select_color(primary bool, idx int) {
|
||||
|
@ -293,10 +312,10 @@ fn (mut app App) select_color(primary bool, idx int) {
|
|||
app.show_msg('set $c_str color idx: $idx', 1)
|
||||
}
|
||||
|
||||
fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) {
|
||||
fn (mut app App) set_pixel(x_ int, y_ int, c ui.Color) {
|
||||
// Term coords start at 1, and adjust for the header
|
||||
x, y := x_ - 1, y_ - 4
|
||||
if y < 0 || app.tui.window_height - y < 3 {
|
||||
if y < 0 || app.ui.window_height - y < 3 {
|
||||
return
|
||||
}
|
||||
if y >= app.drawing.len || x < 0 || x >= app.drawing[0].len {
|
||||
|
@ -305,8 +324,8 @@ fn (mut app App) set_pixel(x_ int, y_ int, c tui.Color) {
|
|||
app.drawing[y][x] = c
|
||||
}
|
||||
|
||||
fn (mut app App) paint(event &tui.Event) {
|
||||
if event.y < 4 || app.tui.window_height - event.y < 4 {
|
||||
fn (mut app App) paint(event &ui.Event) {
|
||||
if event.y < 4 || app.ui.window_height - event.y < 4 {
|
||||
return
|
||||
}
|
||||
x_start, y_start := int(f32((event.x - 1) / 2) - app.size / 2 + 1), event.y - app.size / 2
|
||||
|
@ -323,38 +342,38 @@ fn (mut app App) paint(event &tui.Event) {
|
|||
}
|
||||
|
||||
fn (mut app App) draw_content() {
|
||||
w_, mut h_ := app.tui.window_width / 2, app.tui.window_height - 8
|
||||
w_, mut h_ := app.ui.window_width / 2, app.ui.window_height - 8
|
||||
if h_ > app.drawing.len {
|
||||
h_ = app.drawing.len
|
||||
}
|
||||
for row_idx, row in app.drawing[..h_] {
|
||||
app.tui.set_cursor_position(0, row_idx + 4)
|
||||
mut last := tui.Color{0, 0, 0}
|
||||
app.ui.set_cursor_position(0, row_idx + 4)
|
||||
mut last := ui.Color{0, 0, 0}
|
||||
for cell in row[..w_] {
|
||||
if cell.r == 0 && cell.g == 0 && cell.b == 0 {
|
||||
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
||||
app.tui.reset()
|
||||
app.ui.reset()
|
||||
}
|
||||
} else {
|
||||
if !(cell.r == last.r && cell.g == last.g && cell.b == last.b) {
|
||||
app.tui.set_bg_color(cell)
|
||||
app.ui.set_bg_color(cell)
|
||||
}
|
||||
}
|
||||
app.tui.write(spaces)
|
||||
app.ui.write(spaces)
|
||||
last = cell
|
||||
}
|
||||
app.tui.reset()
|
||||
app.ui.reset()
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut app App) draw_cursor() {
|
||||
if app.mouse_pos.y in [3, app.tui.window_height - 5] {
|
||||
if app.mouse_pos.y in [3, app.ui.window_height - 5] {
|
||||
// inside the horizontal separators
|
||||
return
|
||||
}
|
||||
cursor_color := if app.is_dragging { tui.Color{220, 220, 220} } else { tui.Color{160, 160, 160} }
|
||||
app.tui.set_bg_color(cursor_color)
|
||||
if app.mouse_pos.y >= 3 && app.mouse_pos.y <= app.tui.window_height - 4 {
|
||||
cursor_color := if app.is_dragging { ui.Color{220, 220, 220} } else { ui.Color{160, 160, 160} }
|
||||
app.ui.set_bg_color(cursor_color)
|
||||
if app.mouse_pos.y >= 3 && app.mouse_pos.y <= app.ui.window_height - 4 {
|
||||
// inside the main content
|
||||
mut x_start := int(f32((app.mouse_pos.x - 1) / 2) - app.size / 2 + 1) * 2 - 1
|
||||
mut y_start := app.mouse_pos.y - app.size / 2
|
||||
|
@ -366,70 +385,71 @@ fn (mut app App) draw_cursor() {
|
|||
if y_start < 4 {
|
||||
y_start = 4
|
||||
}
|
||||
if x_end > app.tui.window_width {
|
||||
x_end = app.tui.window_width
|
||||
if x_end > app.ui.window_width {
|
||||
x_end = app.ui.window_width
|
||||
}
|
||||
if y_end > app.tui.window_height - 5 {
|
||||
y_end = app.tui.window_height - 5
|
||||
if y_end > app.ui.window_height - 5 {
|
||||
y_end = app.ui.window_height - 5
|
||||
}
|
||||
app.tui.draw_rect(x_start, y_start, x_end, y_end)
|
||||
app.ui.draw_rect(x_start, y_start, x_end, y_end)
|
||||
} else {
|
||||
app.tui.draw_text(app.mouse_pos.x, app.mouse_pos.y, space)
|
||||
app.ui.draw_text(app.mouse_pos.x, app.mouse_pos.y, space)
|
||||
}
|
||||
app.tui.reset()
|
||||
app.ui.reset()
|
||||
}
|
||||
|
||||
fn (mut app App) draw_header() {
|
||||
if app.msg != '' {
|
||||
app.tui.set_color({
|
||||
app.ui.set_color(
|
||||
r: 0
|
||||
g: 0
|
||||
b: 0
|
||||
})
|
||||
app.tui.set_bg_color({
|
||||
)
|
||||
app.ui.set_bg_color(
|
||||
r: 220
|
||||
g: 220
|
||||
b: 220
|
||||
})
|
||||
app.tui.draw_text(0, 0, ' $app.msg ')
|
||||
app.tui.reset()
|
||||
)
|
||||
app.ui.draw_text(0, 0, ' $app.msg ')
|
||||
app.ui.reset()
|
||||
}
|
||||
app.tui.draw_text(3, 2, /* 'tick: $app.tui.frame_count | ' + */ 'terminal size: ($app.tui.window_width, $app.tui.window_height) | primary color: $app.primary_color.hex() | secondary color: $app.secondary_color.hex()')
|
||||
app.tui.horizontal_separator(3)
|
||||
//'tick: $app.ui.frame_count | ' +
|
||||
app.ui.draw_text(3, 2, 'terminal size: ($app.ui.window_width, $app.ui.window_height) | primary color: $app.primary_color.hex() | secondary color: $app.secondary_color.hex()')
|
||||
app.ui.horizontal_separator(3)
|
||||
}
|
||||
|
||||
fn (mut app App) draw_footer() {
|
||||
_, wh := app.tui.window_width, app.tui.window_height
|
||||
app.tui.horizontal_separator(wh - 4)
|
||||
_, wh := app.ui.window_width, app.ui.window_height
|
||||
app.ui.horizontal_separator(wh - 4)
|
||||
for i, color_row in colors {
|
||||
for j, color in color_row {
|
||||
x := j * 3 + 19
|
||||
y := wh - 3 + i
|
||||
app.tui.set_bg_color(color)
|
||||
app.ui.set_bg_color(color)
|
||||
if app.primary_color_idx == j + (i * 19) {
|
||||
app.tui.set_color(r: 0, g: 0, b: 0)
|
||||
app.tui.draw_text(x, y, '><')
|
||||
app.tui.reset_color()
|
||||
app.ui.set_color(r: 0, g: 0, b: 0)
|
||||
app.ui.draw_text(x, y, '><')
|
||||
app.ui.reset_color()
|
||||
} else if app.secondary_color_idx == j + (i * 19) {
|
||||
app.tui.set_color(r: 255, g: 255, b: 255)
|
||||
app.tui.draw_text(x, y, '><')
|
||||
app.tui.reset_color()
|
||||
app.ui.set_color(r: 255, g: 255, b: 255)
|
||||
app.ui.draw_text(x, y, '><')
|
||||
app.ui.reset_color()
|
||||
} else {
|
||||
app.tui.draw_rect(x, y, x + 1, y)
|
||||
app.ui.draw_rect(x, y, x + 1, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
app.tui.reset_bg_color()
|
||||
app.tui.draw_text(3, wh - 3, select_color)
|
||||
app.tui.bold()
|
||||
app.tui.draw_text(3, wh - 1, '$select_size $app.size')
|
||||
app.tui.reset()
|
||||
app.ui.reset_bg_color()
|
||||
app.ui.draw_text(3, wh - 3, select_color)
|
||||
app.ui.bold()
|
||||
app.ui.draw_text(3, wh - 1, '$select_size $app.size')
|
||||
app.ui.reset()
|
||||
|
||||
// TODO: help button
|
||||
// if ww >= 90 {
|
||||
// app.tui.draw_text(80, wh - 3, help_1)
|
||||
// app.tui.draw_text(80, wh - 2, help_2)
|
||||
// app.tui.draw_text(80, wh - 1, help_3)
|
||||
// app.ui.draw_text(80, wh - 3, help_1)
|
||||
// app.ui.draw_text(80, wh - 2, help_2)
|
||||
// app.ui.draw_text(80, wh - 1, help_3)
|
||||
// }
|
||||
}
|
||||
|
||||
|
@ -449,8 +469,8 @@ fn (mut app App) dec_size() {
|
|||
app.show_msg('dec. size: $app.size', 1)
|
||||
}
|
||||
|
||||
fn (mut app App) footer_click(event &tui.Event) {
|
||||
footer_y := 3 - (app.tui.window_height - event.y)
|
||||
fn (mut app App) footer_click(event &ui.Event) {
|
||||
footer_y := 3 - (app.ui.window_height - event.y)
|
||||
match event.x {
|
||||
8...11 {
|
||||
app.inc_size()
|
||||
|
@ -464,7 +484,9 @@ fn (mut app App) footer_click(event &tui.Event) {
|
|||
return
|
||||
}
|
||||
idx := footer_y * 19 - 6 + event.x / 3
|
||||
if idx < 0 || idx > 56 { return }
|
||||
if idx < 0 || idx > 56 {
|
||||
return
|
||||
}
|
||||
app.select_color(event.button == .left, idx)
|
||||
}
|
||||
else {}
|
||||
|
@ -473,6 +495,6 @@ fn (mut app App) footer_click(event &tui.Event) {
|
|||
|
||||
fn (mut app App) show_msg(text string, time int) {
|
||||
frames := time * frame_rate
|
||||
app.msg_hide_tick = if time > 0 { int(app.tui.frame_count) + frames } else { -1 }
|
||||
app.msg_hide_tick = if time > 0 { int(app.ui.frame_count) + frames } else { -1 }
|
||||
app.msg = text
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ fn (mut a App) set_status(msg string, duration_ms int) {
|
|||
fn (mut a App) save() {
|
||||
if a.cfile().len > 0 {
|
||||
b := a.ed
|
||||
os.write_file(a.cfile(), b.raw())
|
||||
os.write_file(a.cfile(), b.raw()) or { panic(err) }
|
||||
a.set_status('Saved', 2000)
|
||||
} else {
|
||||
a.set_status('No file loaded', 4000)
|
||||
|
@ -79,7 +79,6 @@ fn (mut a App) visit_next_file() {
|
|||
a.init_file()
|
||||
}
|
||||
|
||||
|
||||
fn (mut a App) footer() {
|
||||
w, h := a.tui.window_width, a.tui.window_height
|
||||
mut b := a.ed
|
||||
|
@ -99,16 +98,16 @@ fn (mut a App) footer() {
|
|||
if a.t <= 0 {
|
||||
status = ''
|
||||
} else {
|
||||
a.tui.set_bg_color({
|
||||
a.tui.set_bg_color(
|
||||
r: 200
|
||||
g: 200
|
||||
b: 200
|
||||
})
|
||||
a.tui.set_color({
|
||||
)
|
||||
a.tui.set_color(
|
||||
r: 0
|
||||
g: 0
|
||||
b: 0
|
||||
})
|
||||
)
|
||||
a.tui.draw_text((w + 4 - status.len) / 2, h - 1, ' $status ')
|
||||
a.tui.reset()
|
||||
a.t -= 33
|
||||
|
@ -303,7 +302,7 @@ fn (mut b Buffer) free() {
|
|||
for line in b.lines {
|
||||
line.free()
|
||||
}
|
||||
unsafe {b.lines.free()}
|
||||
unsafe { b.lines.free() }
|
||||
}
|
||||
|
||||
fn (mut b Buffer) move_updown(amount int) {
|
||||
|
@ -334,7 +333,7 @@ fn (mut b Buffer) move_cursor(amount int, movement Movement) {
|
|||
b.move_updown(-dlines)
|
||||
}
|
||||
.page_down {
|
||||
dlines := imin(b.lines.len-1, b.cursor.pos_y + amount) - b.cursor.pos_y
|
||||
dlines := imin(b.lines.len - 1, b.cursor.pos_y + amount) - b.cursor.pos_y
|
||||
b.move_updown(dlines)
|
||||
}
|
||||
.left {
|
||||
|
@ -374,13 +373,19 @@ fn (mut b Buffer) move_to_word(movement Movement) {
|
|||
x = 0
|
||||
}
|
||||
// first, move past all non-`a-zA-Z0-9_` characters
|
||||
for x+a >= 0 && x+a < line.len && !(line[x+a].is_letter() || line[x+a].is_digit() || line[x+a] == `_`) { x += a }
|
||||
for x + a >= 0 && x + a < line.len && !(line[x + a].is_letter()
|
||||
|| line[x + a].is_digit()|| line[x + a] == `_`) {
|
||||
x += a
|
||||
}
|
||||
// then, move past all the letters and numbers
|
||||
for x+a >= 0 && x+a < line.len && (line[x+a].is_letter() || line[x+a].is_digit() || line[x+a] == `_`) { x += a }
|
||||
for x + a >= 0 && x + a < line.len && (line[x + a].is_letter()
|
||||
|| line[x + a].is_digit()|| line[x + a] == `_`) {
|
||||
x += a
|
||||
}
|
||||
// if the cursor is out of bounds, move it to the next/previous line
|
||||
if x + a >= 0 && x + a <= line.len {
|
||||
x += a
|
||||
} else if a < 0 && y+1 > b.lines.len && y-1 >= 0 {
|
||||
} else if a < 0 && y + 1 > b.lines.len && y - 1 >= 0 {
|
||||
y += a
|
||||
x = 0
|
||||
}
|
||||
|
@ -388,11 +393,19 @@ fn (mut b Buffer) move_to_word(movement Movement) {
|
|||
}
|
||||
|
||||
fn imax(x int, y int) int {
|
||||
return if x < y { y } else { x }
|
||||
return if x < y {
|
||||
y
|
||||
} else {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
fn imin(x int, y int) int {
|
||||
return if x < y { x } else { y }
|
||||
return if x < y {
|
||||
x
|
||||
} else {
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
struct Cursor {
|
||||
|
@ -443,9 +456,7 @@ fn (mut a App) init_file() {
|
|||
// 'vico: ' +
|
||||
a.tui.set_window_title(a.files[a.current_file])
|
||||
mut b := a.ed
|
||||
content := os.read_file(a.files[a.current_file]) or {
|
||||
panic(err)
|
||||
}
|
||||
content := os.read_file(a.files[a.current_file]) or { panic(err) }
|
||||
b.put(content)
|
||||
a.ed.cursor.pos_x = init_x
|
||||
a.ed.cursor.pos_y = init_y
|
||||
|
@ -573,12 +584,12 @@ fn main() {
|
|||
mut a := &App{
|
||||
files: files
|
||||
}
|
||||
a.tui = tui.init({
|
||||
a.tui = tui.init(
|
||||
user_data: a
|
||||
init_fn: init
|
||||
frame_fn: frame
|
||||
event_fn: event
|
||||
capture_events: true
|
||||
})
|
||||
a.tui.run()
|
||||
)
|
||||
a.tui.run() ?
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ mut:
|
|||
pos Vec = {
|
||||
x: block_size
|
||||
y: block_size
|
||||
}
|
||||
}
|
||||
color termui.Color = green
|
||||
facing Orientation = .top
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ mut:
|
|||
velocity Vec = Vec{
|
||||
x: 0
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// length returns the snake's current length
|
||||
|
@ -125,8 +125,16 @@ fn (mut s Snake) move() {
|
|||
piece.facing = s.direction
|
||||
new_x := piece.pos.x + s.velocity.x
|
||||
new_y := piece.pos.y + s.velocity.y
|
||||
piece.pos.x += if new_x > block_size && new_x < width - block_size { s.velocity.x } else { 0 }
|
||||
piece.pos.y += if new_y > block_size && new_y < height - block_size { s.velocity.y } else { 0 }
|
||||
piece.pos.x += if new_x > block_size && new_x < width - block_size {
|
||||
s.velocity.x
|
||||
} else {
|
||||
0
|
||||
}
|
||||
piece.pos.y += if new_y > block_size && new_y < height - block_size {
|
||||
s.velocity.y
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
s.body[i] = piece
|
||||
}
|
||||
|
@ -205,10 +213,10 @@ fn (s Snake) check_overlap() bool {
|
|||
|
||||
fn (s Snake) check_out_of_bounds() bool {
|
||||
h := s.get_head()
|
||||
return h.pos.x + s.velocity.x <= block_size ||
|
||||
h.pos.x + s.velocity.x > s.app.width - s.velocity.x || h.pos.y + s.velocity.y <= block_size ||
|
||||
h.pos.y + s.velocity.y >
|
||||
s.app.height - block_size - s.velocity.y
|
||||
return h.pos.x + s.velocity.x <= block_size
|
||||
|| h.pos.x + s.velocity.x > s.app.width - s.velocity.x
|
||||
|| h.pos.y + s.velocity.y <= block_size
|
||||
|| h.pos.y + s.velocity.y > s.app.height - block_size - s.velocity.y
|
||||
}
|
||||
|
||||
// draw draws the parts of the snake
|
||||
|
@ -236,7 +244,7 @@ mut:
|
|||
pos Vec = {
|
||||
x: block_size
|
||||
y: block_size
|
||||
}
|
||||
}
|
||||
captured bool
|
||||
color termui.Color = grey
|
||||
app &App
|
||||
|
@ -244,8 +252,8 @@ mut:
|
|||
|
||||
// randomize spawn the rat in a new spot within the playable field
|
||||
fn (mut r Rat) randomize() {
|
||||
r.pos.randomize(2 * block_size + buffer, 2 * block_size + buffer, r.app.width - block_size -
|
||||
buffer, r.app.height - block_size - buffer)
|
||||
r.pos.randomize(2 * block_size + buffer, 2 * block_size + buffer, r.app.width - block_size - buffer,
|
||||
r.app.height - block_size - buffer)
|
||||
}
|
||||
|
||||
struct App {
|
||||
|
@ -387,9 +395,8 @@ fn (mut a App) move_snake(direction Orientation) {
|
|||
fn (a App) check_capture() bool {
|
||||
snake_pos := a.snake.get_head().pos
|
||||
rat_pos := a.rat.pos
|
||||
return snake_pos.x <= rat_pos.x + block_size &&
|
||||
snake_pos.x + block_size >= rat_pos.x && snake_pos.y <= rat_pos.y + block_size && snake_pos.y +
|
||||
block_size >= rat_pos.y
|
||||
return snake_pos.x <= rat_pos.x + block_size && snake_pos.x + block_size >= rat_pos.x
|
||||
&& snake_pos.y <= rat_pos.y + block_size&& snake_pos.y + block_size >= rat_pos.y
|
||||
}
|
||||
|
||||
fn (mut a App) draw_snake() {
|
||||
|
@ -454,12 +461,12 @@ fn (mut a App) draw_gameover() {
|
|||
}
|
||||
|
||||
mut app := &App{}
|
||||
app.termui = termui.init({
|
||||
app.termui = termui.init(
|
||||
user_data: app
|
||||
event_fn: event
|
||||
frame_fn: frame
|
||||
init_fn: init
|
||||
hide_cursor: true
|
||||
frame_rate: 10
|
||||
})
|
||||
app.termui.run()
|
||||
)
|
||||
app.termui.run() ?
|
||||
|
|
|
@ -16,18 +16,16 @@ fn main() {
|
|||
if line == '' {
|
||||
break
|
||||
}
|
||||
ws.write_str(line)
|
||||
}
|
||||
ws.close(1000, 'normal') or {
|
||||
println(term.red('panicing $err'))
|
||||
ws.write_str(line) ?
|
||||
}
|
||||
ws.close(1000, 'normal') or { println(term.red('panicing $err')) }
|
||||
unsafe {
|
||||
ws.free()
|
||||
}
|
||||
}
|
||||
|
||||
fn start_client() ?&websocket.Client {
|
||||
mut ws := websocket.new_client('ws://localhost:30000')?
|
||||
mut ws := websocket.new_client('ws://localhost:30000') ?
|
||||
// mut ws := websocket.new_client('wss://echo.websocket.org:443')?
|
||||
// use on_open_ref if you want to send any reference object
|
||||
ws.on_open(fn (mut ws websocket.Client) ? {
|
||||
|
@ -49,12 +47,8 @@ fn start_client() ?&websocket.Client {
|
|||
}
|
||||
})
|
||||
|
||||
ws.connect() or {
|
||||
println(term.red('error on connect: $err'))
|
||||
}
|
||||
ws.connect() or { println(term.red('error on connect: $err')) }
|
||||
|
||||
go ws.listen() or {
|
||||
println(term.red('error on listen $err'))
|
||||
}
|
||||
go ws.listen() or { println(term.red('error on listen $err')) }
|
||||
return ws
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ fn (cmd Command) check_version_flag() {
|
|||
version_flag := cmd.flags.get_bool('version') or { return } // ignore error and handle command normally
|
||||
if version_flag {
|
||||
version_cmd := cmd.commands.get('version') or { return } // ignore error and handle command normally
|
||||
version_cmd.execute(version_cmd)
|
||||
version_cmd.execute(version_cmd) or { panic(err) }
|
||||
exit(0)
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ fn (cmd Command) check_required_flags() {
|
|||
pub fn (cmd Command) execute_help() {
|
||||
if cmd.commands.contains('help') {
|
||||
help_cmd := cmd.commands.get('help') or { return } // ignore error and handle command normally
|
||||
help_cmd.execute(help_cmd)
|
||||
help_cmd.execute(help_cmd) or { panic(err) }
|
||||
} else {
|
||||
print(cmd.help_message())
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ fn test_vexe() {
|
|||
|
||||
fn test_can_compile_library() {
|
||||
os.chdir(cfolder)
|
||||
os.rm(library_file_name)
|
||||
os.rm(library_file_name) or { }
|
||||
res := v_compile('-d no_backtrace -o library -shared library.v')
|
||||
eprintln('res: $res')
|
||||
assert os.is_file(library_file_name)
|
||||
|
@ -34,7 +34,7 @@ fn test_can_compile_main_program() {
|
|||
result := v_compile('run use.v')
|
||||
eprintln('result: $result')
|
||||
assert result.output.contains('res: 4')
|
||||
os.rm(library_file_name)
|
||||
os.rm(library_file_name) or { }
|
||||
}
|
||||
|
||||
fn v_compile(vopts string) os.Result {
|
||||
|
|
|
@ -10,16 +10,16 @@ const (
|
|||
|
||||
fn testsuite_begin() {
|
||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { }
|
||||
assert !os.is_dir(tfolder)
|
||||
os.mkdir_all(tfolder)
|
||||
os.mkdir_all(tfolder) or { panic(err) }
|
||||
os.chdir(tfolder)
|
||||
assert os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
fn testsuite_end() {
|
||||
os.chdir(os.wd_at_startup)
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { }
|
||||
assert !os.is_dir(tfolder)
|
||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||
}
|
||||
|
@ -38,9 +38,9 @@ fn test_temp_file() {
|
|||
assert f.is_opened
|
||||
// Test pattern
|
||||
f.close()
|
||||
f, path = util.temp_file({
|
||||
f, path = util.temp_file(
|
||||
pattern: 'some_*_test.file'
|
||||
}) or {
|
||||
) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
|
@ -58,9 +58,9 @@ fn test_temp_file() {
|
|||
// Test custom path
|
||||
prev_path = path
|
||||
f.close()
|
||||
f, path = util.temp_file({
|
||||
f, path = util.temp_file(
|
||||
path: tfolder
|
||||
}) or {
|
||||
) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
|
@ -88,9 +88,9 @@ fn test_temp_dir() {
|
|||
assert writable
|
||||
mut prev_path := path
|
||||
// Test pattern
|
||||
path = util.temp_dir({
|
||||
path = util.temp_dir(
|
||||
pattern: 'some_*_test_dir'
|
||||
}) or {
|
||||
) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
|
@ -106,9 +106,9 @@ fn test_temp_dir() {
|
|||
}
|
||||
// Test custom path
|
||||
prev_path = path
|
||||
path = util.temp_dir({
|
||||
path = util.temp_dir(
|
||||
path: tfolder
|
||||
}) or {
|
||||
) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ pub fn (mut l Log) close() {
|
|||
fn (mut l Log) log_file(s string, level Level) {
|
||||
timestamp := time.now().format_ss()
|
||||
e := tag_to_file(level)
|
||||
l.ofile.writeln('$timestamp [$e] $s')
|
||||
l.ofile.writeln('$timestamp [$e] $s') or { panic(err) }
|
||||
}
|
||||
|
||||
// log_cli writes log line `s` with `level` to stdout.
|
||||
|
|
|
@ -36,7 +36,7 @@ pub fn socket_error(potential_code int) ?int {
|
|||
pub fn wrap_error(error_code int) ? {
|
||||
$if windows {
|
||||
enum_error := wsa_error(error_code)
|
||||
return error_with_code('socket error: $enum_error', error_code)
|
||||
return error_with_code('net: socket error: $enum_error', error_code)
|
||||
}
|
||||
$else {
|
||||
if error_code == 0 {
|
||||
|
|
|
@ -36,7 +36,7 @@ const (
|
|||
|
||||
struct DTP {
|
||||
mut:
|
||||
conn net.TcpConn
|
||||
conn &net.TcpConn
|
||||
reader io.BufferedReader
|
||||
ip string
|
||||
port int
|
||||
|
@ -56,31 +56,31 @@ fn (mut dtp DTP) read() ?[]byte {
|
|||
}
|
||||
|
||||
fn (mut dtp DTP) close() {
|
||||
dtp.conn.close()
|
||||
dtp.conn.close() or { panic(err) }
|
||||
}
|
||||
|
||||
struct FTP {
|
||||
mut:
|
||||
conn net.TcpConn
|
||||
conn &net.TcpConn
|
||||
reader io.BufferedReader
|
||||
buffer_size int
|
||||
}
|
||||
|
||||
pub fn new() FTP {
|
||||
mut f := FTP{}
|
||||
mut f := FTP{ conn: 0 }
|
||||
f.buffer_size = 1024
|
||||
return f
|
||||
}
|
||||
|
||||
fn (mut ftp FTP) write(data string) ? {
|
||||
fn (mut zftp FTP) write(data string) ? {
|
||||
$if debug {
|
||||
println('FTP.v >>> $data')
|
||||
}
|
||||
ftp.conn.write('$data\r\n'.bytes()) ?
|
||||
zftp.conn.write('$data\r\n'.bytes()) ?
|
||||
}
|
||||
|
||||
fn (mut ftp FTP) read() ?(int, string) {
|
||||
mut data := ftp.reader.read_line() ?
|
||||
fn (mut zftp FTP) read() ?(int, string) {
|
||||
mut data := zftp.reader.read_line() ?
|
||||
$if debug {
|
||||
println('FTP.v <<< $data')
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ fn (mut ftp FTP) read() ?(int, string) {
|
|||
code := data[..3].int()
|
||||
if data[3] == `-` {
|
||||
for {
|
||||
data = ftp.reader.read_line() ?
|
||||
data = zftp.reader.read_line() ?
|
||||
if data[..3].int() == code && data[3] != `-` {
|
||||
break
|
||||
}
|
||||
|
@ -99,51 +99,51 @@ fn (mut ftp FTP) read() ?(int, string) {
|
|||
return code, data
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) connect(ip string) ?bool {
|
||||
ftp.conn = net.dial_tcp('$ip:21') ?
|
||||
ftp.reader = io.new_buffered_reader(reader: io.make_reader(ftp.conn))
|
||||
code, _ := ftp.read() ?
|
||||
if code == connected {
|
||||
pub fn (mut zftp FTP) connect(ip string) ?bool {
|
||||
zftp.conn = net.dial_tcp('$ip:21') ?
|
||||
zftp.reader = io.new_buffered_reader(reader: io.make_reader(zftp.conn))
|
||||
code, _ := zftp.read() ?
|
||||
if code == ftp.connected {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) login(user string, passwd string) ?bool {
|
||||
ftp.write('USER $user') or {
|
||||
pub fn (mut zftp FTP) login(user string, passwd string) ?bool {
|
||||
zftp.write('USER $user') or {
|
||||
$if debug {
|
||||
println('ERROR sending user')
|
||||
}
|
||||
return false
|
||||
}
|
||||
mut code, _ := ftp.read() ?
|
||||
if code == logged_in {
|
||||
mut code, _ := zftp.read() ?
|
||||
if code == ftp.logged_in {
|
||||
return true
|
||||
}
|
||||
if code != specify_password {
|
||||
if code != ftp.specify_password {
|
||||
return false
|
||||
}
|
||||
ftp.write('PASS $passwd') or {
|
||||
zftp.write('PASS $passwd') or {
|
||||
$if debug {
|
||||
println('ERROR sending password')
|
||||
}
|
||||
return false
|
||||
}
|
||||
code, _ = ftp.read() ?
|
||||
if code == logged_in {
|
||||
code, _ = zftp.read() ?
|
||||
if code == ftp.logged_in {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) close() ? {
|
||||
ftp.write('QUIT') ?
|
||||
ftp.conn.close()
|
||||
pub fn (mut zftp FTP) close() ? {
|
||||
zftp.write('QUIT') ?
|
||||
zftp.conn.close() ?
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) pwd() ?string {
|
||||
ftp.write('PWD') ?
|
||||
_, data := ftp.read() ?
|
||||
pub fn (mut zftp FTP) pwd() ?string {
|
||||
zftp.write('PWD') ?
|
||||
_, data := zftp.read() ?
|
||||
spl := data.split('"') // "
|
||||
if spl.len >= 2 {
|
||||
return spl[1]
|
||||
|
@ -151,17 +151,17 @@ pub fn (mut ftp FTP) pwd() ?string {
|
|||
return data
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) cd(dir string) ? {
|
||||
ftp.write('CWD $dir') or { return }
|
||||
mut code, mut data := ftp.read() ?
|
||||
pub fn (mut zftp FTP) cd(dir string) ? {
|
||||
zftp.write('CWD $dir') or { return }
|
||||
mut code, mut data := zftp.read() ?
|
||||
match int(code) {
|
||||
denied {
|
||||
ftp.denied {
|
||||
$if debug {
|
||||
println('CD $dir denied!')
|
||||
}
|
||||
}
|
||||
complete {
|
||||
code, data = ftp.read() ?
|
||||
ftp.complete {
|
||||
code, data = zftp.read() ?
|
||||
}
|
||||
else {}
|
||||
}
|
||||
|
@ -178,6 +178,7 @@ fn new_dtp(msg string) ?&DTP {
|
|||
mut dtp := &DTP{
|
||||
ip: ip
|
||||
port: port
|
||||
conn: 0
|
||||
}
|
||||
conn := net.dial_tcp('$ip:$port') or { return error('Cannot connect to the data channel') }
|
||||
dtp.conn = conn
|
||||
|
@ -185,32 +186,32 @@ fn new_dtp(msg string) ?&DTP {
|
|||
return dtp
|
||||
}
|
||||
|
||||
fn (mut ftp FTP) pasv() ?&DTP {
|
||||
ftp.write('PASV') ?
|
||||
code, data := ftp.read() ?
|
||||
fn (mut zftp FTP) pasv() ?&DTP {
|
||||
zftp.write('PASV') ?
|
||||
code, data := zftp.read() ?
|
||||
$if debug {
|
||||
println('pass: $data')
|
||||
}
|
||||
if code != passive_mode {
|
||||
if code != ftp.passive_mode {
|
||||
return error('pasive mode not allowed')
|
||||
}
|
||||
dtp := new_dtp(data) ?
|
||||
return dtp
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) dir() ?[]string {
|
||||
mut dtp := ftp.pasv() or { return error('Cannot establish data connection') }
|
||||
ftp.write('LIST') ?
|
||||
code, _ := ftp.read() ?
|
||||
if code == denied {
|
||||
pub fn (mut zftp FTP) dir() ?[]string {
|
||||
mut dtp := zftp.pasv() or { return error('Cannot establish data connection') }
|
||||
zftp.write('LIST') ?
|
||||
code, _ := zftp.read() ?
|
||||
if code == ftp.denied {
|
||||
return error('`LIST` denied')
|
||||
}
|
||||
if code != open_data_connection {
|
||||
if code != ftp.open_data_connection {
|
||||
return error('Data channel empty')
|
||||
}
|
||||
list_dir := dtp.read() ?
|
||||
result, _ := ftp.read() ?
|
||||
if result != close_data_connection {
|
||||
result, _ := zftp.read() ?
|
||||
if result != ftp.close_data_connection {
|
||||
println('`LIST` not ok')
|
||||
}
|
||||
dtp.close()
|
||||
|
@ -225,14 +226,14 @@ pub fn (mut ftp FTP) dir() ?[]string {
|
|||
return dir
|
||||
}
|
||||
|
||||
pub fn (mut ftp FTP) get(file string) ?[]byte {
|
||||
mut dtp := ftp.pasv() or { return error('Cannot stablish data connection') }
|
||||
ftp.write('RETR $file') ?
|
||||
code, _ := ftp.read() ?
|
||||
if code == denied {
|
||||
pub fn (mut zftp FTP) get(file string) ?[]byte {
|
||||
mut dtp := zftp.pasv() or { return error('Cannot stablish data connection') }
|
||||
zftp.write('RETR $file') ?
|
||||
code, _ := zftp.read() ?
|
||||
if code == ftp.denied {
|
||||
return error('Permission denied')
|
||||
}
|
||||
if code != open_data_connection {
|
||||
if code != ftp.open_data_connection {
|
||||
return error('Data connection not ready')
|
||||
}
|
||||
blob := dtp.read() ?
|
||||
|
|
|
@ -1,42 +1,49 @@
|
|||
import net.ftp
|
||||
|
||||
// NB: this function makes network calls to external servers,
|
||||
// that is why it is not a very good idea to run it in CI.
|
||||
// If you want to run it manually, use `v -d network vlib/net/ftp/ftp_test.v`
|
||||
fn ftp_client_test_inside() ? {
|
||||
$if !network ? { return }
|
||||
mut ftp := ftp.new()
|
||||
defer {
|
||||
ftp.close()
|
||||
fn test_ftp_cleint() {
|
||||
$if !network ? {
|
||||
return
|
||||
}
|
||||
connect_result := ftp.connect('ftp.redhat.com')?
|
||||
// NB: this function makes network calls to external servers,
|
||||
// that is why it is not a very good idea to run it in CI.
|
||||
// If you want to run it manually, use:
|
||||
// `v -d network vlib/net/ftp/ftp_test.v`
|
||||
ftp_client_test_inside() or { panic(err) }
|
||||
}
|
||||
|
||||
fn ftp_client_test_inside() ? {
|
||||
mut zftp := ftp.new()
|
||||
// eprintln(zftp)
|
||||
defer {
|
||||
zftp.close() or { panic(err) }
|
||||
}
|
||||
connect_result := zftp.connect('ftp.redhat.com') ?
|
||||
assert connect_result
|
||||
login_result := ftp.login('ftp', 'ftp')?
|
||||
login_result := zftp.login('ftp', 'ftp') ?
|
||||
assert login_result
|
||||
pwd := ftp.pwd()?
|
||||
pwd := zftp.pwd() ?
|
||||
assert pwd.len > 0
|
||||
ftp.cd('/')
|
||||
dir_list1 := ftp.dir() or {
|
||||
zftp.cd('/') or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
dir_list1 := zftp.dir() or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert dir_list1.len > 0
|
||||
ftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/')
|
||||
dir_list2 := ftp.dir() or {
|
||||
zftp.cd('/suse/linux/enterprise/11Server/en/SAT-TOOLS/SRPMS/') or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
dir_list2 := zftp.dir() or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert dir_list2.len > 0
|
||||
blob := ftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
|
||||
blob := zftp.get('katello-host-tools-3.3.5-8.sles11_4sat.src.rpm') or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
assert blob.len > 0
|
||||
}
|
||||
|
||||
|
||||
fn test_ftp_cleint() {
|
||||
ftp_client_test_inside() or {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,11 @@ module http
|
|||
|
||||
import os
|
||||
|
||||
pub fn download_file(url string, out string)? {
|
||||
$if debug_http? {
|
||||
pub fn download_file(url string, out string) ? {
|
||||
$if debug_http ? {
|
||||
println('download file url=$url out=$out')
|
||||
}
|
||||
s := get(url) or {
|
||||
return error(err)
|
||||
}
|
||||
os.write_file(out, s.text)
|
||||
s := get(url) or { return error(err) }
|
||||
os.write_file(out, s.text) ?
|
||||
// download_file_with_progress(url, out, empty, empty)
|
||||
}
|
||||
|
|
|
@ -67,33 +67,48 @@ pub fn get(url string) ?Response {
|
|||
}
|
||||
|
||||
pub fn post(url string, data string) ?Response {
|
||||
return fetch_with_method(.post, url, data: data, headers: {
|
||||
'Content-Type': content_type_default
|
||||
})
|
||||
return fetch_with_method(.post, url,
|
||||
data: data
|
||||
headers: {
|
||||
'Content-Type': http.content_type_default
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn post_json(url string, data string) ?Response {
|
||||
return fetch_with_method(.post, url, data: data, headers: {
|
||||
return fetch_with_method(.post, url,
|
||||
data: data
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn post_form(url string, data map[string]string) ?Response {
|
||||
return fetch_with_method(.post, url, headers: {
|
||||
return fetch_with_method(.post, url,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
}, data: url_encode_form_data(data))
|
||||
}
|
||||
data: url_encode_form_data(data)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn put(url string, data string) ?Response {
|
||||
return fetch_with_method(.put, url, data: data, headers: {
|
||||
'Content-Type': content_type_default
|
||||
})
|
||||
return fetch_with_method(.put, url,
|
||||
data: data
|
||||
headers: {
|
||||
'Content-Type': http.content_type_default
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn patch(url string, data string) ?Response {
|
||||
return fetch_with_method(.patch, url, data: data, headers: {
|
||||
'Content-Type': content_type_default
|
||||
})
|
||||
return fetch_with_method(.patch, url,
|
||||
data: data
|
||||
headers: {
|
||||
'Content-Type': http.content_type_default
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
pub fn head(url string) ?Response {
|
||||
|
@ -165,11 +180,11 @@ fn build_url_from_fetch(_url string, config FetchConfig) ?string {
|
|||
}
|
||||
|
||||
fn (mut req Request) free() {
|
||||
unsafe {req.headers.free()}
|
||||
unsafe { req.headers.free() }
|
||||
}
|
||||
|
||||
fn (mut resp Response) free() {
|
||||
unsafe {resp.headers.free()}
|
||||
unsafe { resp.headers.free() }
|
||||
}
|
||||
|
||||
// add_header adds the key and value of an HTTP request header
|
||||
|
@ -199,8 +214,8 @@ pub fn (req &Request) do() ?Response {
|
|||
mut resp := Response{}
|
||||
mut no_redirects := 0
|
||||
for {
|
||||
if no_redirects == max_redirects {
|
||||
return error('http.request.do: maximum number of redirects reached ($max_redirects)')
|
||||
if no_redirects == http.max_redirects {
|
||||
return error('http.request.do: maximum number of redirects reached ($http.max_redirects)')
|
||||
}
|
||||
qresp := req.method_and_url_to_response(req.method, rurl) ?
|
||||
resp = qresp
|
||||
|
@ -366,7 +381,7 @@ fn (req &Request) http_do(host string, method Method, path string) ?Response {
|
|||
// TODO this really needs to be exposed somehow
|
||||
client.write(s.bytes()) ?
|
||||
mut bytes := io.read_all(reader: client) ?
|
||||
client.close()
|
||||
client.close() ?
|
||||
return parse_response(bytes.bytestr())
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,8 @@ pub fn (mut c Client) send(config Mail) ? {
|
|||
|
||||
// quit closes the connection to the server
|
||||
pub fn (mut c Client) quit() ? {
|
||||
c.send_str('QUIT\r\n')
|
||||
c.expect_reply(.close)
|
||||
c.send_str('QUIT\r\n') ?
|
||||
c.expect_reply(.close) ?
|
||||
c.conn.close() ?
|
||||
c.is_open = false
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ fn (mut c Client) send_mailto(to string) ? {
|
|||
|
||||
fn (mut c Client) send_data() ? {
|
||||
c.send_str('DATA\r\n') ?
|
||||
c.expect_reply(.mail_start)
|
||||
c.expect_reply(.mail_start) ?
|
||||
}
|
||||
|
||||
fn (mut c Client) send_body(cfg Mail) ? {
|
||||
|
|
|
@ -22,8 +22,8 @@ pub fn dial_tcp(address string) ?&TcpConn {
|
|||
s.connect(address) ?
|
||||
return &TcpConn{
|
||||
sock: s
|
||||
read_timeout: tcp_default_read_timeout
|
||||
write_timeout: tcp_default_write_timeout
|
||||
read_timeout: net.tcp_default_read_timeout
|
||||
write_timeout: net.tcp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,8 @@ pub fn (mut c TcpConn) close() ? {
|
|||
// write_ptr blocks and attempts to write all data
|
||||
pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
|
||||
$if trace_tcp ? {
|
||||
eprintln('>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
eprintln(
|
||||
'>>> TcpConn.write_ptr | c.sock.handle: $c.sock.handle | b: ${ptr_str(b)} len: $len |\n' +
|
||||
unsafe { b.vstring_with_len(len) })
|
||||
}
|
||||
unsafe {
|
||||
|
@ -48,7 +49,7 @@ pub fn (mut c TcpConn) write_ptr(b byteptr, len int) ? {
|
|||
if sent < 0 {
|
||||
code := error_code()
|
||||
if code == int(error_ewouldblock) {
|
||||
c.wait_for_write()
|
||||
c.wait_for_write() ?
|
||||
continue
|
||||
} else {
|
||||
wrap_error(code) ?
|
||||
|
@ -164,9 +165,9 @@ pub fn (c &TcpConn) peer_ip() ?string {
|
|||
return res
|
||||
}
|
||||
|
||||
pub fn (c &TcpConn) str() string {
|
||||
// TODO
|
||||
return 'TcpConn {write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $c.sock}'
|
||||
pub fn (c TcpConn) str() string {
|
||||
s := c.sock.str().replace('\n', ' ').replace(' ', ' ')
|
||||
return 'TcpConn{ write_deadline: $c.write_deadline, read_deadline: $c.read_deadline, read_timeout: $c.read_timeout, write_timeout: $c.write_timeout, sock: $s }'
|
||||
}
|
||||
|
||||
pub struct TcpListener {
|
||||
|
@ -213,8 +214,8 @@ pub fn (mut l TcpListener) accept() ?&TcpConn {
|
|||
new_sock := tcp_socket_from_handle(new_handle) ?
|
||||
return &TcpConn{
|
||||
sock: new_sock
|
||||
read_timeout: tcp_default_read_timeout
|
||||
write_timeout: tcp_default_write_timeout
|
||||
read_timeout: net.tcp_default_read_timeout
|
||||
write_timeout: net.tcp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,7 +267,7 @@ fn new_tcp_socket() ?TcpSocket {
|
|||
t := true
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||
} $else {
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK)) ?
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -281,7 +282,7 @@ fn tcp_socket_from_handle(sockfd int) ?TcpSocket {
|
|||
t := true
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||
} $else {
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK))
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFL, C.fcntl(sockfd, C.F_GETFL) | C.O_NONBLOCK)) ?
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
@ -322,12 +323,12 @@ fn (mut s TcpSocket) connect(a string) ? {
|
|||
return none
|
||||
}
|
||||
_ := error_code()
|
||||
write_result := s.@select(.write, connect_timeout) ?
|
||||
write_result := s.@select(.write, net.connect_timeout) ?
|
||||
if write_result {
|
||||
// succeeded
|
||||
return none
|
||||
}
|
||||
except_result := s.@select(.except, connect_timeout) ?
|
||||
except_result := s.@select(.except, net.connect_timeout) ?
|
||||
if except_result {
|
||||
return err_connect_failed
|
||||
}
|
||||
|
|
|
@ -64,7 +64,10 @@ fn test_socket_write_and_read() {
|
|||
message1 := 'a message 1'
|
||||
socket.write_str(message1) or { assert false }
|
||||
mut rbuf := []byte{len: message1.len}
|
||||
client.read(mut rbuf)
|
||||
client.read(mut rbuf) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
line := rbuf.bytestr()
|
||||
assert line == message1
|
||||
}
|
||||
|
@ -127,8 +130,14 @@ fn test_socket_read_line_long_line_without_eol() {
|
|||
cleanup(mut server, mut client, mut socket)
|
||||
}
|
||||
message := strings.repeat_string('123', 400)
|
||||
socket.write_str(message)
|
||||
socket.write_str('\n')
|
||||
socket.write_str(message) or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
socket.write_str('\n') or {
|
||||
assert false
|
||||
return
|
||||
}
|
||||
line := reader.read_line() or {
|
||||
assert false
|
||||
return
|
||||
|
|
|
@ -33,8 +33,8 @@ pub fn dial_udp(laddr string, raddr string) ?&UdpConn {
|
|||
}
|
||||
return &UdpConn{
|
||||
sock: sock
|
||||
read_timeout: udp_default_read_timeout
|
||||
write_timeout: udp_default_write_timeout
|
||||
read_timeout: net.udp_default_read_timeout
|
||||
write_timeout: net.udp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,8 +162,8 @@ pub fn listen_udp(port int) ?&UdpConn {
|
|||
s := new_udp_socket(port) ?
|
||||
return &UdpConn{
|
||||
sock: s
|
||||
read_timeout: udp_default_read_timeout
|
||||
write_timeout: udp_default_write_timeout
|
||||
read_timeout: net.udp_default_read_timeout
|
||||
write_timeout: net.udp_default_write_timeout
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ fn new_udp_socket(local_port int) ?&UdpSocket {
|
|||
t := true
|
||||
socket_error(C.ioctlsocket(sockfd, fionbio, &t)) ?
|
||||
} $else {
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK))
|
||||
socket_error(C.fcntl(sockfd, C.F_SETFD, C.O_NONBLOCK)) ?
|
||||
}
|
||||
// In UDP we always have to bind to a port
|
||||
validate_port(local_port) ?
|
||||
|
|
|
@ -53,8 +53,8 @@ fn should_escape(c byte, mode EncodingMode) bool {
|
|||
// we could possibly allow, and parse will reject them if we
|
||||
// escape them (because hosts can`t use %-encoding for
|
||||
// ASCII bytes).
|
||||
if c in
|
||||
[`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
|
||||
if
|
||||
c in [`!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `:`, `[`, `]`, `<`, `>`, `"`] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
|||
if s.len > 3 {
|
||||
s = s[..3]
|
||||
}
|
||||
return error(error_msg(err_msg_escape, s))
|
||||
return error(error_msg(urllib.err_msg_escape, s))
|
||||
}
|
||||
// Per https://tools.ietf.org/html/rfc3986#page-21
|
||||
// in the host component %-encoding can only be used
|
||||
|
@ -171,7 +171,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
|||
// introduces %25 being allowed to escape a percent sign
|
||||
// in IPv6 scoped-address literals. Yay.
|
||||
if mode == .encode_host && unhex(s[i + 1]) < 8 && s[i..i + 3] != '%25' {
|
||||
return error(error_msg(err_msg_escape, s[i..i + 3]))
|
||||
return error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
|
||||
}
|
||||
if mode == .encode_zone {
|
||||
// RFC 6874 says basically 'anything goes' for zone identifiers
|
||||
|
@ -183,7 +183,7 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
|||
// But Windows puts spaces here! Yay.
|
||||
v := ((unhex(s[i + 1]) << byte(4)) | unhex(s[i + 2]))
|
||||
if s[i..i + 3] != '%25' && v != ` ` && should_escape(v, .encode_host) {
|
||||
error(error_msg(err_msg_escape, s[i..i + 3]))
|
||||
error(error_msg(urllib.err_msg_escape, s[i..i + 3]))
|
||||
}
|
||||
}
|
||||
i += 3
|
||||
|
@ -193,9 +193,8 @@ fn unescape(s_ string, mode EncodingMode) ?string {
|
|||
i++
|
||||
}
|
||||
else {
|
||||
if (mode == .encode_host ||
|
||||
mode == .encode_zone) &&
|
||||
s[i] < 0x80 && should_escape(s[i], mode) {
|
||||
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80
|
||||
&& should_escape(s[i], mode) {
|
||||
error(error_msg('unescape: invalid character in host name', s[i..i + 1]))
|
||||
}
|
||||
i++
|
||||
|
@ -429,11 +428,12 @@ fn split(s string, sep byte, cutc bool) (string, string) {
|
|||
pub fn parse(rawurl string) ?URL {
|
||||
// Cut off #frag
|
||||
u, frag := split(rawurl, `#`, true)
|
||||
mut url := parse_url(u, false) or { return error(error_msg(err_msg_parse, u)) }
|
||||
mut url := parse_url(u, false) or { return error(error_msg(urllib.err_msg_parse, u)) }
|
||||
if frag == '' {
|
||||
return url
|
||||
}
|
||||
f := unescape(frag, .encode_fragment) or { return error(error_msg(err_msg_parse, u)) }
|
||||
f := unescape(frag, .encode_fragment) or { return error(error_msg(urllib.err_msg_parse,
|
||||
u)) }
|
||||
url.fragment = f
|
||||
return url
|
||||
}
|
||||
|
@ -570,7 +570,7 @@ fn parse_host(host string) ?string {
|
|||
// parse an IP-Literal in RFC 3986 and RFC 6874.
|
||||
// E.g., '[fe80::1]', '[fe80::1%25en0]', '[fe80::1]:80'.
|
||||
mut i := host.last_index(']') or {
|
||||
return error(error_msg("parse_host: missing \']\' in host", ''))
|
||||
return error(error_msg("parse_host: missing ']' in host", ''))
|
||||
}
|
||||
mut colon_port := host[i + 1..]
|
||||
if !valid_optional_port(colon_port) {
|
||||
|
@ -785,7 +785,7 @@ pub fn parse_query(query string) ?Values {
|
|||
// but any errors will be silent
|
||||
fn parse_query_silent(query string) Values {
|
||||
mut m := new_values()
|
||||
parse_query_values(mut m, query)
|
||||
parse_query_values(mut m, query) or { }
|
||||
return m
|
||||
}
|
||||
|
||||
|
@ -1029,7 +1029,8 @@ pub fn valid_userinfo(s string) bool {
|
|||
continue
|
||||
}
|
||||
match r {
|
||||
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`, `@` {
|
||||
`-`, `.`, `_`, `:`, `~`, `!`, `$`, `&`, `\\`, `(`, `)`, `*`, `+`, `,`, `;`, `=`, `%`,
|
||||
`@` {
|
||||
continue
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -9,16 +9,16 @@ const (
|
|||
|
||||
fn testsuite_begin() {
|
||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { }
|
||||
assert !os.is_dir(tfolder)
|
||||
os.mkdir_all(tfolder)
|
||||
os.mkdir_all(tfolder) or { panic(err) }
|
||||
os.chdir(tfolder)
|
||||
assert os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
fn testsuite_end() {
|
||||
os.chdir(os.wd_at_startup)
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { panic(err) }
|
||||
assert !os.is_dir(tfolder)
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ fn test_inode_file_type() {
|
|||
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
||||
file.close()
|
||||
mode := os.inode(filename)
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
assert mode.typ == .regular
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ fn test_inode_file_owner_permission() {
|
|||
mut file := os.open_file(filename, 'w', 0o600) or { return }
|
||||
file.close()
|
||||
mode := os.inode(filename)
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { }
|
||||
assert mode.owner.read
|
||||
assert mode.owner.write
|
||||
assert !mode.owner.execute
|
||||
|
|
10
vlib/os/os.v
10
vlib/os/os.v
|
@ -46,7 +46,7 @@ pub fn cp_all(src string, dst string, overwrite bool) ? {
|
|||
}
|
||||
if exists(adjusted_path) {
|
||||
if overwrite {
|
||||
rm(adjusted_path)
|
||||
rm(adjusted_path) ?
|
||||
} else {
|
||||
return error('Destination file path already exist')
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ pub fn cp_all(src string, dst string, overwrite bool) ? {
|
|||
mkdir(dp) ?
|
||||
}
|
||||
cp_all(sp, dp, overwrite) or {
|
||||
rmdir(dp)
|
||||
rmdir(dp) or { return error(err) }
|
||||
return error(err)
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ pub fn file_exists(_path string) bool {
|
|||
[deprecated]
|
||||
pub fn rmdir_recursive(path string) {
|
||||
eprintln('warning: `os.rmdir_recursive` has been deprecated, use `os.rmdir_all` instead')
|
||||
rmdir_all(path)
|
||||
rmdir_all(path) or { panic(err) }
|
||||
}
|
||||
|
||||
// rmdir_all recursively removes the specified directory.
|
||||
|
@ -154,7 +154,7 @@ pub fn rmdir_all(path string) ? {
|
|||
for item in items {
|
||||
fullpath := join_path(path, item)
|
||||
if is_dir(fullpath) {
|
||||
rmdir_all(fullpath)
|
||||
rmdir_all(fullpath) or { ret_err = err }
|
||||
}
|
||||
rm(fullpath) or { ret_err = err }
|
||||
}
|
||||
|
@ -315,7 +315,7 @@ pub fn home_dir() string {
|
|||
// write_file writes `text` data to a file in `path`.
|
||||
pub fn write_file(path string, text string) ? {
|
||||
mut f := create(path) ?
|
||||
f.write(text.bytes())
|
||||
f.write(text.bytes()) ?
|
||||
f.close()
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ pub fn is_writable_folder(folder string) ?bool {
|
|||
}
|
||||
C.close(x)
|
||||
}
|
||||
rm(tmp_perm_check)
|
||||
rm(tmp_perm_check) ?
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
@ -13,9 +13,9 @@ const args_at_start = os.args.clone()
|
|||
|
||||
fn testsuite_begin() {
|
||||
eprintln('testsuite_begin, tfolder = $tfolder')
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { }
|
||||
assert !os.is_dir(tfolder)
|
||||
os.mkdir_all(tfolder)
|
||||
os.mkdir_all(tfolder) or { panic(err) }
|
||||
os.chdir(tfolder)
|
||||
assert os.is_dir(tfolder)
|
||||
// println('args_at_start: $args_at_start')
|
||||
|
@ -25,7 +25,7 @@ fn testsuite_begin() {
|
|||
|
||||
fn testsuite_end() {
|
||||
os.chdir(os.wd_at_startup)
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { }
|
||||
assert !os.is_dir(tfolder)
|
||||
// eprintln('testsuite_end , tfolder = $tfolder removed.')
|
||||
}
|
||||
|
@ -38,12 +38,12 @@ fn test_open_file() {
|
|||
os.File{}
|
||||
}
|
||||
mut file := os.open_file(filename, 'w+', 0o666) or { panic(err) }
|
||||
file.write_str(hello)
|
||||
file.write_str(hello) or { panic(err) }
|
||||
file.close()
|
||||
assert hello.len == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||
assert hello == read_hello
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_open_file_binary() {
|
||||
|
@ -60,7 +60,7 @@ fn test_open_file_binary() {
|
|||
assert hello.len == os.file_size(filename)
|
||||
read_hello := os.read_bytes(filename) or { panic('error reading file $filename') }
|
||||
assert bytes == read_hello
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
|
||||
// fn test_file_get_line() {
|
||||
|
@ -87,23 +87,23 @@ fn test_create_file() {
|
|||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
mut f := os.create(filename) or { panic(err) }
|
||||
f.write_str(hello)
|
||||
f.write_str(hello) or { panic(err) }
|
||||
f.close()
|
||||
assert hello.len == os.file_size(filename)
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_is_file() {
|
||||
// Setup
|
||||
work_dir := os.join_path(os.getwd(), 'is_file_test')
|
||||
os.mkdir_all(work_dir)
|
||||
os.mkdir_all(work_dir) or { panic(err) }
|
||||
tfile := os.join_path(work_dir, 'tmp_file')
|
||||
// Test things that shouldn't be a file
|
||||
assert os.is_file(work_dir) == false
|
||||
assert os.is_file('non-existent_file.tmp') == false
|
||||
// Test file
|
||||
tfile_content := 'temporary file'
|
||||
os.write_file(tfile, tfile_content)
|
||||
os.write_file(tfile, tfile_content) or { panic(err) }
|
||||
assert os.is_file(tfile)
|
||||
// Test dir symlinks
|
||||
$if windows {
|
||||
|
@ -126,11 +126,11 @@ fn test_is_file() {
|
|||
fn test_write_and_read_string_to_file() {
|
||||
filename := './test1.txt'
|
||||
hello := 'hello world!'
|
||||
os.write_file(filename, hello)
|
||||
os.write_file(filename, hello) or { panic(err) }
|
||||
assert hello.len == os.file_size(filename)
|
||||
read_hello := os.read_file(filename) or { panic('error reading file $filename') }
|
||||
assert hello == read_hello
|
||||
os.rm(filename)
|
||||
os.rm(filename) or { panic(err) }
|
||||
}
|
||||
|
||||
// test_write_and_read_bytes checks for regressions made in the functions
|
||||
|
@ -166,7 +166,7 @@ fn test_write_and_read_bytes() {
|
|||
assert nread == 0
|
||||
file_read.close()
|
||||
// We finally delete the test file.
|
||||
os.rm(file_name)
|
||||
os.rm(file_name) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_create_and_delete_folder() {
|
||||
|
@ -175,7 +175,7 @@ fn test_create_and_delete_folder() {
|
|||
assert os.is_dir(folder)
|
||||
folder_contents := os.ls(folder) or { panic(err) }
|
||||
assert folder_contents.len == 0
|
||||
os.rmdir(folder)
|
||||
os.rmdir(folder) or { panic(err) }
|
||||
folder_exists := os.is_dir(folder)
|
||||
assert folder_exists == false
|
||||
}
|
||||
|
@ -191,61 +191,61 @@ fn test_walk() {
|
|||
folder := 'test_walk'
|
||||
os.mkdir(folder) or { panic(err) }
|
||||
file1 := folder + os.path_separator + 'test1'
|
||||
os.write_file(file1, 'test-1')
|
||||
os.write_file(file1, 'test-1') or { panic(err) }
|
||||
os.walk(folder, walk_callback)
|
||||
os.rm(file1)
|
||||
os.rmdir(folder)
|
||||
os.rm(file1) or { panic(err) }
|
||||
os.rmdir(folder) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_cp() {
|
||||
old_file_name := 'cp_example.txt'
|
||||
new_file_name := 'cp_new_example.txt'
|
||||
os.write_file(old_file_name, 'Test data 1 2 3, V is awesome #$%^[]!~⭐')
|
||||
os.write_file(old_file_name, 'Test data 1 2 3, V is awesome #$%^[]!~⭐') or { panic(err) }
|
||||
os.cp(old_file_name, new_file_name) or { panic('$err: errcode: $errcode') }
|
||||
old_file := os.read_file(old_file_name) or { panic(err) }
|
||||
new_file := os.read_file(new_file_name) or { panic(err) }
|
||||
assert old_file == new_file
|
||||
os.rm(old_file_name)
|
||||
os.rm(new_file_name)
|
||||
os.rm(old_file_name) or { panic(err) }
|
||||
os.rm(new_file_name) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_mv() {
|
||||
work_dir := os.join_path(os.getwd(), 'mv_test')
|
||||
os.mkdir_all(work_dir)
|
||||
os.mkdir_all(work_dir) or { panic(err) }
|
||||
// Setup test files
|
||||
tfile1 := os.join_path(work_dir, 'file')
|
||||
tfile2 := os.join_path(work_dir, 'file.test')
|
||||
tfile3 := os.join_path(work_dir, 'file.3')
|
||||
tfile_content := 'temporary file'
|
||||
os.write_file(tfile1, tfile_content)
|
||||
os.write_file(tfile2, tfile_content)
|
||||
os.write_file(tfile1, tfile_content) or { panic(err) }
|
||||
os.write_file(tfile2, tfile_content) or { panic(err) }
|
||||
// Setup test dirs
|
||||
tdir1 := os.join_path(work_dir, 'dir')
|
||||
tdir2 := os.join_path(work_dir, 'dir2')
|
||||
tdir3 := os.join_path(work_dir, 'dir3')
|
||||
mkdir(tdir1)
|
||||
mkdir(tdir2)
|
||||
os.mkdir(tdir1) or { panic(err) }
|
||||
os.mkdir(tdir2) or { panic(err) }
|
||||
// Move file with no extension to dir
|
||||
os.mv(tfile1, tdir1)
|
||||
os.mv(tfile1, tdir1) or { panic(err) }
|
||||
mut expected := os.join_path(tdir1, 'file')
|
||||
assert os.exists(expected) && !is_dir(expected) == true
|
||||
// Move dir with contents to other dir
|
||||
os.mv(tdir1, tdir2)
|
||||
os.mv(tdir1, tdir2) or { panic(err) }
|
||||
expected = os.join_path(tdir2, 'dir')
|
||||
assert os.exists(expected) && is_dir(expected) == true
|
||||
expected = os.join_path(tdir2, 'dir', 'file')
|
||||
assert os.exists(expected) && !is_dir(expected) == true
|
||||
// Move dir with contents to other dir (by renaming)
|
||||
os.mv(os.join_path(tdir2, 'dir'), tdir3)
|
||||
os.mv(os.join_path(tdir2, 'dir'), tdir3) or { panic(err) }
|
||||
expected = tdir3
|
||||
assert os.exists(expected) && is_dir(expected) == true
|
||||
assert os.is_dir_empty(tdir2) == true
|
||||
// Move file with extension to dir
|
||||
os.mv(tfile2, tdir2)
|
||||
os.mv(tfile2, tdir2) or { panic(err) }
|
||||
expected = os.join_path(tdir2, 'file.test')
|
||||
assert os.exists(expected) && !is_dir(expected) == true
|
||||
// Move file to dir (by renaming)
|
||||
os.mv(os.join_path(tdir2, 'file.test'), tfile3)
|
||||
os.mv(os.join_path(tdir2, 'file.test'), tfile3) or { panic(err) }
|
||||
expected = tfile3
|
||||
assert os.exists(expected) && !is_dir(expected) == true
|
||||
}
|
||||
|
@ -253,14 +253,14 @@ fn test_mv() {
|
|||
fn test_cp_r() {
|
||||
// fileX -> dir/fileX
|
||||
// NB: clean up of the files happens inside the cleanup_leftovers function
|
||||
os.write_file('ex1.txt', 'wow!')
|
||||
os.write_file('ex1.txt', 'wow!') or { panic(err) }
|
||||
os.mkdir('ex') or { panic(err) }
|
||||
os.cp_all('ex1.txt', 'ex', false) or { panic(err) }
|
||||
old := os.read_file('ex1.txt') or { panic(err) }
|
||||
new := os.read_file('ex/ex1.txt') or { panic(err) }
|
||||
assert old == new
|
||||
os.mkdir('ex/ex2') or { panic(err) }
|
||||
os.write_file('ex2.txt', 'great!')
|
||||
os.write_file('ex2.txt', 'great!') or { panic(err) }
|
||||
os.cp_all('ex2.txt', 'ex/ex2', false) or { panic(err) }
|
||||
old2 := os.read_file('ex2.txt') or { panic(err) }
|
||||
new2 := os.read_file('ex/ex2/ex2.txt') or { panic(err) }
|
||||
|
@ -274,12 +274,12 @@ fn test_tmpdir() {
|
|||
assert t.len > 0
|
||||
assert os.is_dir(t)
|
||||
tfile := t + os.path_separator + 'tmpfile.txt'
|
||||
os.rm(tfile) // just in case
|
||||
os.rm(tfile) or { } // just in case
|
||||
tfile_content := 'this is a temporary file'
|
||||
os.write_file(tfile, tfile_content)
|
||||
os.write_file(tfile, tfile_content) or { panic(err) }
|
||||
tfile_content_read := os.read_file(tfile) or { panic(err) }
|
||||
assert tfile_content_read == tfile_content
|
||||
os.rm(tfile)
|
||||
os.rm(tfile) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_is_writable_folder() {
|
||||
|
@ -299,15 +299,15 @@ fn test_make_symlink_check_is_link_and_remove_symlink() {
|
|||
}
|
||||
folder := 'tfolder'
|
||||
symlink := 'tsymlink'
|
||||
os.rm(symlink)
|
||||
os.rm(folder)
|
||||
os.rm(symlink) or { }
|
||||
os.rm(folder) or { }
|
||||
os.mkdir(folder) or { panic(err) }
|
||||
folder_contents := os.ls(folder) or { panic(err) }
|
||||
assert folder_contents.len == 0
|
||||
os.system('ln -s $folder $symlink')
|
||||
assert os.is_link(symlink) == true
|
||||
os.rm(symlink)
|
||||
os.rm(folder)
|
||||
os.rm(symlink) or { panic(err) }
|
||||
os.rm(folder) or { panic(err) }
|
||||
folder_exists := os.is_dir(folder)
|
||||
assert folder_exists == false
|
||||
symlink_exists := os.is_link(symlink)
|
||||
|
@ -343,8 +343,8 @@ fn test_symlink() {
|
|||
os.symlink('symlink', 'symlink2') or { panic(err) }
|
||||
assert os.exists('symlink2')
|
||||
// cleanup
|
||||
os.rm('symlink')
|
||||
os.rm('symlink2')
|
||||
os.rm('symlink') or { panic(err) }
|
||||
os.rm('symlink2') or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_is_executable_writable_readable() {
|
||||
|
@ -367,7 +367,7 @@ fn test_is_executable_writable_readable() {
|
|||
assert os.is_executable(file_name)
|
||||
}
|
||||
// We finally delete the test file.
|
||||
os.rm(file_name)
|
||||
os.rm(file_name) or { panic(err) }
|
||||
}
|
||||
|
||||
fn test_ext() {
|
||||
|
@ -438,7 +438,7 @@ fn test_write_file_array_bytes() {
|
|||
for i in 0 .. maxn {
|
||||
arr[i] = 65 + byte(i)
|
||||
}
|
||||
os.write_file_array(fpath, arr)
|
||||
os.write_file_array(fpath, arr) or { panic(err) }
|
||||
rarr := os.read_bytes(fpath) or { panic(err) }
|
||||
assert arr == rarr
|
||||
// eprintln(arr.str())
|
||||
|
@ -451,7 +451,7 @@ fn test_write_file_array_structs() {
|
|||
for i in 0 .. maxn {
|
||||
arr[i] = IntPoint{65 + i, 65 + i + 10}
|
||||
}
|
||||
os.write_file_array(fpath, arr)
|
||||
os.write_file_array(fpath, arr) or { panic(err) }
|
||||
rarr := os.read_file_array<IntPoint>(fpath)
|
||||
assert rarr == arr
|
||||
assert rarr.len == maxn
|
||||
|
@ -519,6 +519,6 @@ fn test_posix_set_bit() {
|
|||
}
|
||||
mode = u32(s.st_mode) & 0o7777
|
||||
assert mode == 0o0755
|
||||
rm(fpath)
|
||||
rm(fpath) or { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@ import time
|
|||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
fn C.tcgetattr()
|
||||
|
||||
fn C.tcsetattr()
|
||||
|
||||
fn C.ioctl(fd int, request u64, arg voidptr) int
|
||||
|
||||
struct C.termios {
|
||||
|
@ -103,7 +104,6 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
// feature-test rgb (truecolor) support
|
||||
ctx.enable_rgb = supports_truecolor()
|
||||
}
|
||||
|
||||
// Prevent stdin from blocking by making its read time 0
|
||||
termios.c_cc[C.VTIME] = 0
|
||||
termios.c_cc[C.VMIN] = 0
|
||||
|
@ -124,7 +124,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
os.signal(C.SIGCONT, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.termios_setup()
|
||||
c.termios_setup() or { panic(err) }
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
mut event := &Event{
|
||||
typ: .resized
|
||||
|
@ -136,7 +136,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
}
|
||||
})
|
||||
for code in ctx.cfg.reset {
|
||||
os.signal(code, fn() {
|
||||
os.signal(code, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.cleanup()
|
||||
|
@ -145,7 +145,7 @@ fn (mut ctx Context) termios_setup() ? {
|
|||
})
|
||||
}
|
||||
|
||||
os.signal(C.SIGWINCH, fn() {
|
||||
os.signal(C.SIGWINCH, fn () {
|
||||
mut c := ctx_ptr
|
||||
if c != 0 {
|
||||
c.window_height, c.window_width = get_terminal_size()
|
||||
|
@ -166,10 +166,14 @@ fn get_cursor_position() (int, int) {
|
|||
print('\033[6n')
|
||||
buf := malloc(25)
|
||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||
unsafe { buf[len] = 0 }
|
||||
unsafe {
|
||||
buf[len] = 0
|
||||
}
|
||||
s := tos(buf, len)
|
||||
a := s[2..].split(';')
|
||||
if a.len != 2 { return -1, -1 }
|
||||
if a.len != 2 {
|
||||
return -1, -1
|
||||
}
|
||||
return a[0].int(), a[1].int()
|
||||
}
|
||||
|
||||
|
@ -184,14 +188,16 @@ fn supports_truecolor() bool {
|
|||
print('\x1bP\$qm\x1b\\')
|
||||
buf := malloc(25)
|
||||
len := C.read(C.STDIN_FILENO, buf, 24)
|
||||
unsafe { buf[len] = 0 }
|
||||
unsafe {
|
||||
buf[len] = 0
|
||||
}
|
||||
s := tos(buf, len)
|
||||
return '1:2:3' in s
|
||||
|
||||
}
|
||||
|
||||
fn termios_reset() {
|
||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH /* C.TCSANOW ?? */, &termios_at_startup)
|
||||
// C.TCSANOW ??
|
||||
C.tcsetattr(C.STDIN_FILENO, C.TCSAFLUSH, &ui.termios_at_startup)
|
||||
print('\x1b[?1003l\x1b[?1006l\x1b[?25h')
|
||||
c := ctx_ptr
|
||||
if c != 0 && c.cfg.use_alternate_buffer {
|
||||
|
@ -201,7 +207,6 @@ fn termios_reset() {
|
|||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
// TODO: do multiple sleep/read cycles, rather than one big one
|
||||
fn (mut ctx Context) termios_loop() {
|
||||
frame_time := 1_000_000 / ctx.cfg.frame_rate
|
||||
|
@ -221,7 +226,8 @@ fn (mut ctx Context) termios_loop() {
|
|||
sw.restart()
|
||||
if ctx.cfg.event_fn != voidptr(0) {
|
||||
unsafe {
|
||||
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len, ctx.read_buf.cap - ctx.read_buf.len)
|
||||
len := C.read(C.STDIN_FILENO, byteptr(ctx.read_buf.data) + ctx.read_buf.len,
|
||||
ctx.read_buf.cap - ctx.read_buf.len)
|
||||
ctx.resize_arr(ctx.read_buf.len + len)
|
||||
}
|
||||
if ctx.read_buf.len > 0 {
|
||||
|
@ -243,7 +249,9 @@ fn (mut ctx Context) parse_events() {
|
|||
mut nr_iters := 0
|
||||
for ctx.read_buf.len > 0 {
|
||||
nr_iters++
|
||||
if nr_iters > 100 { ctx.shift(1) }
|
||||
if nr_iters > 100 {
|
||||
ctx.shift(1)
|
||||
}
|
||||
mut event := &Event(0)
|
||||
if ctx.read_buf[0] == 0x1b {
|
||||
e, len := escape_sequence(ctx.read_buf.bytestr())
|
||||
|
@ -272,41 +280,52 @@ fn single_char(buf string) &Event {
|
|||
|
||||
match ch {
|
||||
// special handling for `ctrl + letter`
|
||||
|
||||
// TODO: Fix assoc in V and remove this workaround :/
|
||||
// 1 ... 26 { event = Event{ ...event, code: KeyCode(96 | ch), modifiers: ctrl } }
|
||||
// 65 ... 90 { event = Event{ ...event, code: KeyCode(32 | ch), modifiers: shift } }
|
||||
|
||||
|
||||
// The bit `or`s here are really just `+`'s, just written in this way for a tiny performance improvement
|
||||
// don't treat tab, enter as ctrl+i, ctrl+j
|
||||
1 ... 8, 11 ... 26 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(96 | ch), modifiers: ctrl } }
|
||||
65 ... 90 { event = &Event{ typ: event.typ, ascii: event.ascii, utf8: event.utf8, code: KeyCode(32 | ch), modifiers: shift } }
|
||||
|
||||
1...8, 11...26 { event = &Event{
|
||||
typ: event.typ
|
||||
ascii: event.ascii
|
||||
utf8: event.utf8
|
||||
code: KeyCode(96 | ch)
|
||||
modifiers: ctrl
|
||||
} }
|
||||
65...90 { event = &Event{
|
||||
typ: event.typ
|
||||
ascii: event.ascii
|
||||
utf8: event.utf8
|
||||
code: KeyCode(32 | ch)
|
||||
modifiers: shift
|
||||
} }
|
||||
else {}
|
||||
}
|
||||
|
||||
return event
|
||||
}
|
||||
|
||||
[inline]
|
||||
// Gets an entire, independent escape sequence from the buffer
|
||||
// Normally, this just means reading until the first letter, but there are some exceptions...
|
||||
fn escape_end(buf string) int {
|
||||
mut i := 0
|
||||
for {
|
||||
if i + 1 == buf.len { return buf.len }
|
||||
if i + 1 == buf.len {
|
||||
return buf.len
|
||||
}
|
||||
|
||||
if buf[i].is_letter() || buf[i] == `~` {
|
||||
if buf[i] == `O` && i + 2 <= buf.len {
|
||||
n := buf[i+1]
|
||||
n := buf[i + 1]
|
||||
if (n >= `A` && n <= `D`) || (n >= `P` && n <= `S`) || n == `F` || n == `H` {
|
||||
return i + 2
|
||||
}
|
||||
}
|
||||
return i + 1
|
||||
// escape hatch to avoid potential issues/crashes, although ideally this should never eval to true
|
||||
} else if buf[i + 1] == 0x1b { return i + 1 }
|
||||
} else if buf[i + 1] == 0x1b {
|
||||
return i + 1
|
||||
}
|
||||
i++
|
||||
}
|
||||
// this point should be unreachable
|
||||
|
@ -339,32 +358,49 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
|||
modifiers: c.modifiers | alt
|
||||
}, 2
|
||||
}
|
||||
|
||||
// ----------------
|
||||
// Mouse events
|
||||
// ----------------
|
||||
|
||||
// Documentation: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking
|
||||
if buf.len > 2 && buf[1] == `<` {
|
||||
split := buf[2..].split(';')
|
||||
if split.len < 3 { return &Event(0), 0 }
|
||||
if split.len < 3 {
|
||||
return &Event(0), 0
|
||||
}
|
||||
|
||||
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
||||
lo := typ & 0b00011
|
||||
hi := typ & 0b11100
|
||||
|
||||
mut modifiers := u32(0)
|
||||
if hi & 4 != 0 { modifiers |= shift }
|
||||
if hi & 8 != 0 { modifiers |= alt }
|
||||
if hi & 16 != 0 { modifiers |= ctrl }
|
||||
if hi & 4 != 0 {
|
||||
modifiers |= shift
|
||||
}
|
||||
if hi & 8 != 0 {
|
||||
modifiers |= alt
|
||||
}
|
||||
if hi & 16 != 0 {
|
||||
modifiers |= ctrl
|
||||
}
|
||||
|
||||
match typ {
|
||||
0...31 {
|
||||
last := buf[buf.len - 1]
|
||||
button := if lo < 3 { MouseButton(lo + 1) } else { MouseButton.unknown }
|
||||
event := if last == `m` || lo == 3 { EventType.mouse_up } else { EventType.mouse_down }
|
||||
event := if last == `m` || lo == 3 {
|
||||
EventType.mouse_up
|
||||
} else {
|
||||
EventType.mouse_down
|
||||
}
|
||||
|
||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers utf8: single }, end
|
||||
return &Event{
|
||||
typ: event
|
||||
x: x
|
||||
y: y
|
||||
button: button
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
32...63 {
|
||||
button, event := if lo < 3 {
|
||||
|
@ -373,17 +409,34 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
|||
MouseButton.unknown, EventType.mouse_move
|
||||
}
|
||||
|
||||
return &Event{ typ: event, x: x, y: y, button: button, modifiers: modifiers, utf8: single }, end
|
||||
return &Event{
|
||||
typ: event
|
||||
x: x
|
||||
y: y
|
||||
button: button
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
64...95 {
|
||||
direction := if typ & 1 == 0 { Direction.down } else { Direction.up }
|
||||
return &Event{ typ: .mouse_scroll, x: x, y: y, direction: direction, modifiers: modifiers, utf8: single }, end
|
||||
} else {
|
||||
return &Event{ typ: .unknown, utf8: single }, end
|
||||
return &Event{
|
||||
typ: .mouse_scroll
|
||||
x: x
|
||||
y: y
|
||||
direction: direction
|
||||
modifiers: modifiers
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
else {
|
||||
return &Event{
|
||||
typ: .unknown
|
||||
utf8: single
|
||||
}, end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Special key combinations
|
||||
// ----------------------------
|
||||
|
@ -455,5 +508,10 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
|||
}
|
||||
}
|
||||
|
||||
return &Event{ typ: .key_down, code: code, utf8: single, modifiers: modifiers }, end
|
||||
return &Event{
|
||||
typ: .key_down
|
||||
code: code
|
||||
utf8: single
|
||||
modifiers: modifiers
|
||||
}, end
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ pub fn (mut b Builder) build_c(v_files []string, out_file string) {
|
|||
b.info('build_c($out_file)')
|
||||
output2 := b.gen_c(v_files)
|
||||
mut f := os.create(out_file) or { panic(err) }
|
||||
f.writeln(output2)
|
||||
f.writeln(output2) or { panic(err) }
|
||||
f.close()
|
||||
// os.write_file(out_file, b.gen_c(v_files))
|
||||
}
|
||||
|
@ -75,9 +75,9 @@ pub fn (mut b Builder) compile_c() {
|
|||
bundle_name := b.pref.out_name.split('/').last()
|
||||
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||
os.mkdir('${display_name}.app')
|
||||
os.mkdir('${display_name}.app') or { panic(err) }
|
||||
os.write_file('${display_name}.app/Info.plist', make_ios_plist(display_name, bundle_id,
|
||||
bundle_name, 1))
|
||||
bundle_name, 1)) or { panic(err) }
|
||||
}
|
||||
b.cc()
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ fn (mut v Builder) post_process_c_compiler_output(res os.Result) {
|
|||
if v.pref.is_verbose {
|
||||
eprintln('>> remove tmp file: $tmpfile')
|
||||
}
|
||||
os.rm(tmpfile)
|
||||
os.rm(tmpfile) or { panic(err) }
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -414,7 +414,9 @@ fn (mut v Builder) setup_output_name() {
|
|||
if v.pref.is_verbose {
|
||||
println('Building $v.pref.path to $v.pref.out_name ...')
|
||||
}
|
||||
v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n')
|
||||
v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n') or {
|
||||
panic(err)
|
||||
}
|
||||
// println('v.table.imports:')
|
||||
// println(v.table.imports)
|
||||
}
|
||||
|
@ -734,7 +736,7 @@ fn (mut b Builder) cc_linux_cross() {
|
|||
b.setup_output_name()
|
||||
parent_dir := os.vmodules_dir()
|
||||
if !os.exists(parent_dir) {
|
||||
os.mkdir(parent_dir)
|
||||
os.mkdir(parent_dir) or { panic(err) }
|
||||
}
|
||||
sysroot := os.join_path(os.vmodules_dir(), 'linuxroot')
|
||||
if !os.is_dir(sysroot) {
|
||||
|
@ -917,7 +919,7 @@ fn (mut v Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CF
|
|||
// for example thirdparty\tcc\lib\openlibm.o
|
||||
// the best we can do for them is just copy them,
|
||||
// and hope that they work with any compiler...
|
||||
os.cp(obj_path, opath)
|
||||
os.cp(obj_path, opath) or { panic(err) }
|
||||
return
|
||||
}
|
||||
println('$obj_path not found, building it in $opath ...')
|
||||
|
@ -943,7 +945,9 @@ fn (mut v Builder) build_thirdparty_obj_file(path string, moduleflags []cflag.CF
|
|||
verror(res.output)
|
||||
return
|
||||
}
|
||||
v.pref.cache_manager.save('.description.txt', obj_path, '${obj_path:-30} @ $cmd\n')
|
||||
v.pref.cache_manager.save('.description.txt', obj_path, '${obj_path:-30} @ $cmd\n') or {
|
||||
panic(err)
|
||||
}
|
||||
println(res.output)
|
||||
}
|
||||
|
||||
|
|
|
@ -93,12 +93,12 @@ fn (mut b Builder) run_compiled_executable_and_exit() {
|
|||
}
|
||||
if b.pref.os == .ios {
|
||||
device := '"iPhone SE (2nd generation)"'
|
||||
os.exec('xcrun simctl boot $device')
|
||||
os.exec('xcrun simctl boot $device') or { panic(err) }
|
||||
bundle_name := b.pref.out_name.split('/').last()
|
||||
display_name := if b.pref.display_name != '' { b.pref.display_name } else { bundle_name }
|
||||
os.exec('xcrun simctl install $device ${display_name}.app')
|
||||
os.exec('xcrun simctl install $device ${display_name}.app') or { panic(err) }
|
||||
bundle_id := if b.pref.bundle_id != '' { b.pref.bundle_id } else { 'app.vlang.$bundle_name' }
|
||||
os.exec('xcrun simctl launch $device $bundle_id')
|
||||
os.exec('xcrun simctl launch $device $bundle_id') or { panic(err) }
|
||||
} else {
|
||||
exefile := os.real_path(b.pref.out_name)
|
||||
mut cmd := '"$exefile"'
|
||||
|
@ -133,7 +133,7 @@ fn (mut v Builder) cleanup_run_executable_after_exit(exefile string) {
|
|||
}
|
||||
if os.is_file(exefile) {
|
||||
v.pref.vrun_elog('remove run executable: $exefile')
|
||||
os.rm(exefile)
|
||||
os.rm(exefile) or { panic(err) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ pub fn (mut b Builder) build_js(v_files []string, out_file string) {
|
|||
b.info('build_js($out_file)')
|
||||
output := b.gen_js(v_files)
|
||||
mut f := os.create(out_file) or { panic(err) }
|
||||
f.writeln(output)
|
||||
f.writeln(output) or { panic(err) }
|
||||
f.close()
|
||||
}
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ pub fn (mut v Builder) cc_msvc() {
|
|||
// println(res)
|
||||
// println('C OUTPUT:')
|
||||
// Always remove the object file - it is completely unnecessary
|
||||
os.rm(out_name_obj)
|
||||
os.rm(out_name_obj) or { panic(err) }
|
||||
}
|
||||
|
||||
fn (mut v Builder) build_thirdparty_obj_file_with_msvc(path string, moduleflags []cflag.CFlag) {
|
||||
|
|
|
@ -1930,10 +1930,8 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
|||
if expr is ast.CallExpr {
|
||||
if expr.return_type.has_flag(.optional) {
|
||||
if expr.or_block.kind == .absent {
|
||||
if ret_type != table.void_type {
|
||||
c.error('${expr.name}() returns an option but is missing an `or {}` block',
|
||||
c.error('${expr.name}() returns an option, so it should have either an `or {}` block, or `?` at the end',
|
||||
expr.pos)
|
||||
}
|
||||
} else {
|
||||
c.check_or_expr(expr.or_block, ret_type, expr.return_type.clear_flag(.optional))
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/optional_method_err.vv:17:10: error: inc_to_limit() returns an option but is missing an `or {}` block
|
||||
vlib/v/checker/tests/optional_method_err.vv:17:10: error: inc_to_limit() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||
15 | mut a := Abc{}
|
||||
16 | for _ in 0 .. 4 {
|
||||
17 | _ := a.inc_to_limit(2)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
vlib/v/checker/tests/optional_void_called_as_normal.vv:7:2: error: foo() returns an option, so it should have either an `or {}` block, or `?` at the end
|
||||
5 | fn main() {
|
||||
6 | // Calling foo() without ? or an or block, should be an error.
|
||||
7 | foo()
|
||||
| ~~~~~
|
||||
8 | }
|
|
@ -0,0 +1,8 @@
|
|||
fn foo() ? {
|
||||
println('foo is called')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Calling foo() without ? or an or block, should be an error.
|
||||
foo()
|
||||
}
|
|
@ -13,7 +13,7 @@ const skip_files = [
|
|||
|
||||
const skip_on_ubuntu_musl = [
|
||||
'vlib/v/checker/tests/vweb_tmpl_used_var.vv',
|
||||
]
|
||||
]
|
||||
|
||||
const turn_off_vcolors = os.setenv('VCOLORS', 'never', true)
|
||||
|
||||
|
@ -179,7 +179,7 @@ fn (mut task TaskDescription) execute() {
|
|||
res := os.exec(cli_cmd) or { panic(err) }
|
||||
expected_out_path := program.replace('.vv', '') + task.result_extension
|
||||
if should_autofix && !os.exists(expected_out_path) {
|
||||
os.write_file(expected_out_path, '')
|
||||
os.write_file(expected_out_path, '') or { panic(err) }
|
||||
}
|
||||
mut expected := os.read_file(expected_out_path) or { panic(err) }
|
||||
task.expected = clean_line_endings(expected)
|
||||
|
@ -192,7 +192,7 @@ fn (mut task TaskDescription) execute() {
|
|||
if task.expected != task.found___ {
|
||||
task.is_error = true
|
||||
if should_autofix {
|
||||
os.write_file(expected_out_path, res.output)
|
||||
os.write_file(expected_out_path, res.output) or { panic(err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ fn test_fmt() {
|
|||
continue
|
||||
}
|
||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||
os.write_file(vfmt_result_file, result_ocontent)
|
||||
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ fn test_fmt() {
|
|||
continue
|
||||
}
|
||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||
os.write_file(vfmt_result_file, result_ocontent)
|
||||
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ fn test_vlib_fmt() {
|
|||
continue
|
||||
}
|
||||
vfmt_result_file := os.join_path(tmpfolder, 'vfmt_run_over_$ifilename')
|
||||
os.write_file(vfmt_result_file, result_ocontent)
|
||||
os.write_file(vfmt_result_file, result_ocontent) or { panic(err) }
|
||||
eprintln(util.color_compare_files(diff_cmd, opath, vfmt_result_file))
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ const (
|
|||
)
|
||||
|
||||
fn testsuite_end() {
|
||||
os.rmdir_all(main.output_dir)
|
||||
os.rmdir_all(output_dir) or { }
|
||||
}
|
||||
|
||||
const there_is_node_available = is_nodejs_working()
|
||||
|
@ -15,22 +15,22 @@ const there_is_node_available = is_nodejs_working()
|
|||
fn test_example_compilation() {
|
||||
vexe := os.getenv('VEXE')
|
||||
os.chdir(os.dir(vexe))
|
||||
os.mkdir_all(main.output_dir)
|
||||
os.mkdir_all(output_dir) or { panic(err) }
|
||||
files := find_test_files()
|
||||
for file in files {
|
||||
path := os.join_path(main.test_dir, file)
|
||||
path := os.join_path(test_dir, file)
|
||||
println('Testing $file')
|
||||
v_code := os.system('$vexe $main.v_options -o $main.output_dir${file}.js $path')
|
||||
v_code := os.system('$vexe $v_options -o $output_dir${file}.js $path')
|
||||
if v_code != 0 {
|
||||
assert false
|
||||
}
|
||||
// Compilation failed
|
||||
assert v_code == 0
|
||||
if !main.there_is_node_available {
|
||||
if !there_is_node_available {
|
||||
println(' ... skipping running $file, there is no NodeJS present')
|
||||
continue
|
||||
}
|
||||
js_code := os.system('node $main.output_dir${file}.js')
|
||||
js_code := os.system('node $output_dir${file}.js')
|
||||
if js_code != 0 {
|
||||
assert false
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ fn test_example_compilation() {
|
|||
}
|
||||
|
||||
fn find_test_files() []string {
|
||||
files := os.ls(main.test_dir) or { panic(err) }
|
||||
files := os.ls(test_dir) or { panic(err) }
|
||||
// The life example never exits, so tests would hang with it, skip
|
||||
mut tests := files.filter(it.ends_with('.v')).filter(it != 'life.v')
|
||||
tests.sort()
|
||||
|
|
|
@ -15,12 +15,10 @@ fn test_x64() {
|
|||
vexe := os.getenv('VEXE')
|
||||
vroot := os.dir(vexe)
|
||||
dir := os.join_path(vroot, 'vlib/v/gen/x64/tests')
|
||||
files := os.ls(dir) or {
|
||||
panic(err)
|
||||
}
|
||||
files := os.ls(dir) or { panic(err) }
|
||||
//
|
||||
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'x64')
|
||||
os.mkdir_all(wrkdir)
|
||||
os.mkdir_all(wrkdir) or { panic(err) }
|
||||
os.chdir(wrkdir)
|
||||
tests := files.filter(it.ends_with('.vv'))
|
||||
if tests.len == 0 {
|
||||
|
@ -48,9 +46,7 @@ fn test_x64() {
|
|||
eprintln(res.output)
|
||||
continue
|
||||
}
|
||||
mut expected := os.read_file('$dir/${test}.out') or {
|
||||
panic(err)
|
||||
}
|
||||
mut expected := os.read_file('$dir/${test}.out') or { panic(err) }
|
||||
expected = expected.trim_right('\r\n').replace('\r\n', '\n')
|
||||
mut found := res.output.trim_right('\r\n').replace('\r\n', '\n')
|
||||
found = found.trim_space()
|
||||
|
|
|
@ -127,7 +127,7 @@ fn protected_load_lib(mut r live.LiveReloadInfo, new_lib_path string) {
|
|||
elog(r, '> load_lib OK, new live_lib: $r.live_lib')
|
||||
// removing the .so file from the filesystem after dlopen-ing
|
||||
// it is safe, since it will still be mapped in memory
|
||||
os.rm(new_lib_path)
|
||||
os.rm(new_lib_path) or { }
|
||||
}
|
||||
|
||||
// NB: r.reloader() is executed in a new, independent thread
|
||||
|
|
|
@ -60,8 +60,8 @@ fn atomic_write_source(source string) {
|
|||
// NB: here wrtiting is done in 2 steps, since os.write_file can take some time,
|
||||
// during which the file will be modified, but it will still be not completely written.
|
||||
// The os.mv after that, guarantees that the reloader will see a complete valid V program.
|
||||
os.write_file(tmp_file, source)
|
||||
os.mv(tmp_file, source_file)
|
||||
os.write_file(tmp_file, source) or { panic(err) }
|
||||
os.mv(tmp_file, source_file) or { panic(err) }
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -75,7 +75,7 @@ fn testsuite_begin() {
|
|||
for f in [tmp_file, source_file, output_file, res_original_file, res_changed_file, res_another_file,
|
||||
res_stop_file,
|
||||
] {
|
||||
os.rm(f)
|
||||
os.rm(f) or { }
|
||||
}
|
||||
atomic_write_source(live_program_source)
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ fn testsuite_end() {
|
|||
assert histogram['CHANGED'] + histogram['ANOTHER'] > 0
|
||||
// assert histogram['END'] > 0
|
||||
for tfile in cleanup_files {
|
||||
os.rm(tfile)
|
||||
os.rm(tfile) or { }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@ fn append_to_file(fname string, s string) {
|
|||
println('>>>> could not open file $fname for appending, err: $err ')
|
||||
return
|
||||
}
|
||||
f.writeln(s)
|
||||
//info := live.info()
|
||||
//f.writeln('>>> reloads: ${info.reloads} | ok reloads: ${info.reloads_ok}')
|
||||
f.writeln(s) or {
|
||||
println('>>>> could not write to $fname, err: $err ')
|
||||
return
|
||||
}
|
||||
// info := live.info()
|
||||
// f.writeln('>>> reloads: ${info.reloads} | ok reloads: ${info.reloads_ok}')
|
||||
f.close()
|
||||
}
|
||||
|
||||
|
@ -29,6 +32,7 @@ fn pmessage() string {
|
|||
const (
|
||||
delay = 20
|
||||
)
|
||||
|
||||
fn edefault(name string, default string) string {
|
||||
res := os.getenv(name)
|
||||
if res == '' {
|
||||
|
@ -36,6 +40,7 @@ fn edefault(name string, default string) string {
|
|||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fn main() {
|
||||
mut info := live.info()
|
||||
info.recheck_period_ms = 5
|
||||
|
@ -45,7 +50,7 @@ fn main() {
|
|||
pmessage()
|
||||
max_cycles := edefault('LIVE_CYCLES', '1').int()
|
||||
// NB: 1000 * 20 = maximum of ~20s runtime
|
||||
for i:=0; i<max_cycles; i++ {
|
||||
for i := 0; i < max_cycles; i++ {
|
||||
s := pmessage()
|
||||
myprintln(s)
|
||||
append_to_file(os.resource_abs_path(s + '.txt'), s)
|
||||
|
|
|
@ -112,7 +112,10 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
|||
if op == .decl_assign {
|
||||
// a, b := a + 1, b
|
||||
for r in right {
|
||||
p.check_undefined_variables(left, r)
|
||||
p.check_undefined_variables(left, r) or {
|
||||
p.error('check_undefined_variables failed')
|
||||
return ast.Stmt{}
|
||||
}
|
||||
}
|
||||
} else if left.len > 1 {
|
||||
// a, b = b, a
|
||||
|
|
|
@ -94,7 +94,7 @@ pub fn (mut m Main) run() ?string {
|
|||
res += pcdep.description
|
||||
}
|
||||
if pc != 0 {
|
||||
pc.extend(pcdep)
|
||||
pc.extend(pcdep) ?
|
||||
} else {
|
||||
pc = pcdep
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ fn (mut pc PkgConfig) resolve(pkgname string) ?string {
|
|||
}
|
||||
|
||||
pub fn atleast(v string) bool {
|
||||
v0 := semver.from(version) or { return false }
|
||||
v0 := semver.from(pkgconfig.version) or { return false }
|
||||
v1 := semver.from(v) or { return false }
|
||||
return v0.gt(v1)
|
||||
}
|
||||
|
@ -207,8 +207,8 @@ fn (mut pc PkgConfig) load_require(dep string) ? {
|
|||
if !pcdep.parse(depfile) {
|
||||
return error('required file "$depfile" could not be parsed')
|
||||
}
|
||||
pcdep.load_requires() or { return error(err) }
|
||||
pc.extend(pcdep)
|
||||
pcdep.load_requires() ?
|
||||
pc.extend(pcdep) ?
|
||||
}
|
||||
|
||||
fn (mut pc PkgConfig) add_path(path string) {
|
||||
|
@ -223,7 +223,7 @@ fn (mut pc PkgConfig) add_path(path string) {
|
|||
|
||||
fn (mut pc PkgConfig) load_paths() {
|
||||
if pc.options.use_default_paths {
|
||||
for path in default_paths {
|
||||
for path in pkgconfig.default_paths {
|
||||
pc.add_path(path)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -474,10 +474,10 @@ pub fn parse_args(args []string) (&Preferences, string) {
|
|||
//
|
||||
if output_option.len != 0 {
|
||||
res.vrun_elog('remove tmp exe file: $tmp_exe_file_path')
|
||||
os.rm(tmp_exe_file_path)
|
||||
os.rm(tmp_exe_file_path) or { }
|
||||
}
|
||||
res.vrun_elog('remove tmp v file: $tmp_v_file_path')
|
||||
os.rm(tmp_v_file_path)
|
||||
os.rm(tmp_v_file_path) or { panic(err) }
|
||||
exit(tmp_result)
|
||||
}
|
||||
must_exist(res.path)
|
||||
|
|
|
@ -33,13 +33,13 @@ fn test_all() {
|
|||
panic(err)
|
||||
}
|
||||
$if windows {
|
||||
os.rm('./test.exe')
|
||||
os.rm('./test.exe') or { }
|
||||
$if msvc {
|
||||
os.rm('./test.ilk')
|
||||
os.rm('./test.pdb')
|
||||
os.rm('./test.ilk') or { }
|
||||
os.rm('./test.pdb') or { }
|
||||
}
|
||||
} $else {
|
||||
os.rm('./test')
|
||||
os.rm('./test') or { }
|
||||
}
|
||||
// println('============')
|
||||
// println(res.output)
|
||||
|
|
|
@ -64,7 +64,7 @@ fn worker_repl(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
|||
tls_bench.cstep = idx
|
||||
tfolder := os.join_path(cdir, 'vrepl_tests_$idx')
|
||||
if os.is_dir(tfolder) {
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { panic(err) }
|
||||
}
|
||||
os.mkdir(tfolder) or { panic(err) }
|
||||
file := p.get_string_item(idx)
|
||||
|
@ -73,14 +73,14 @@ fn worker_repl(mut p sync.PoolProcessor, idx int, thread_id int) voidptr {
|
|||
fres := runner.run_repl_file(tfolder, session.options.vexec, file) or {
|
||||
session.bmark.fail()
|
||||
tls_bench.fail()
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { panic(err) }
|
||||
eprintln(tls_bench.step_message_fail(err))
|
||||
assert false
|
||||
return sync.no_result
|
||||
}
|
||||
session.bmark.ok()
|
||||
tls_bench.ok()
|
||||
os.rmdir_all(tfolder)
|
||||
os.rmdir_all(tfolder) or { panic(err) }
|
||||
println(tls_bench.step_message_ok(fres))
|
||||
assert true
|
||||
return sync.no_result
|
||||
|
|
|
@ -35,37 +35,34 @@ pub fn full_path_to_v(dirs_in int) string {
|
|||
}
|
||||
|
||||
fn diff_files(file_result string, file_expected string) string {
|
||||
diffcmd := util.find_working_diff_command() or {
|
||||
return err
|
||||
}
|
||||
diffcmd := util.find_working_diff_command() or { return err }
|
||||
return util.color_compare_files(diffcmd, file_result, file_expected)
|
||||
}
|
||||
|
||||
pub fn run_repl_file(wd string, vexec string, file string) ?string {
|
||||
vexec_folder := os.dir(vexec) + os.path_separator
|
||||
fcontent := os.read_file(file) or {
|
||||
return error('Could not read file $file')
|
||||
}
|
||||
fcontent := os.read_file(file) or { return error('Could not read file $file') }
|
||||
content := fcontent.replace('\r', '')
|
||||
input := content.all_before('===output===\n')
|
||||
output := content.all_after('===output===\n').trim_right('\n\r')
|
||||
fname := os.file_name(file)
|
||||
input_temporary_filename := os.real_path(os.join_path(wd, 'input_temporary_filename.txt'))
|
||||
os.write_file(input_temporary_filename, input)
|
||||
os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent)
|
||||
os.write_file(input_temporary_filename, input) or { panic(err) }
|
||||
os.write_file(os.real_path(os.join_path(wd, 'original.txt')), fcontent) or { panic(err) }
|
||||
rcmd := '"$vexec" repl -replfolder "$wd" -replprefix "${fname}." < $input_temporary_filename'
|
||||
r := os.exec(rcmd) or {
|
||||
os.rm(input_temporary_filename)
|
||||
os.rm(input_temporary_filename) or { panic(err) }
|
||||
return error('Could not execute: $rcmd')
|
||||
}
|
||||
os.rm(input_temporary_filename)
|
||||
os.rm(input_temporary_filename) or { panic(err) }
|
||||
result := r.output.replace('\r', '').replace('>>> ', '').replace('>>>', '').replace('... ',
|
||||
'').replace(wd + os.path_separator, '').replace(vexec_folder, '').replace('\\', '/').trim_right('\n\r')
|
||||
'').replace(wd + os.path_separator, '').replace(vexec_folder, '').replace('\\',
|
||||
'/').trim_right('\n\r')
|
||||
if result != output {
|
||||
file_result := '${file}.result.txt'
|
||||
file_expected := '${file}.expected.txt'
|
||||
os.write_file(file_result, result)
|
||||
os.write_file(file_expected, output)
|
||||
os.write_file(file_result, result) or { panic(err) }
|
||||
os.write_file(file_expected, output) or { panic(err) }
|
||||
diff := diff_files(file_result, file_expected)
|
||||
return error('Difference found in REPL file: $file
|
||||
====> Got :
|
||||
|
@ -87,16 +84,14 @@ pub fn run_prod_file(wd string, vexec string, file string) ?string {
|
|||
}
|
||||
expected_content := f_expected_content.replace('\r', '')
|
||||
cmd := '"$vexec" -prod run "$file"'
|
||||
r := os.exec(cmd) or {
|
||||
return error('Could not execute: $cmd')
|
||||
}
|
||||
r := os.exec(cmd) or { return error('Could not execute: $cmd') }
|
||||
if r.exit_code != 0 {
|
||||
return error('$cmd return exit code: $r.exit_code')
|
||||
}
|
||||
result := r.output.replace('\r', '')
|
||||
if result != expected_content {
|
||||
file_result := '${file}.result.txt'
|
||||
os.write_file(file_result, result)
|
||||
os.write_file(file_result, result) or { panic(err) }
|
||||
diff := diff_files(file_result, file_expected)
|
||||
return error('Difference found in test: $file
|
||||
====> Got :
|
||||
|
|
|
@ -19,7 +19,7 @@ fn pipe_to_v_run() ? {
|
|||
// eprintln('>> cmd: $cmd | res: $res')
|
||||
assert res.exit_code == 0
|
||||
assert res.output.replace('\r', '').trim_space().split('\n') == ['4', 'hello']
|
||||
os.rm(tmp_v_file)
|
||||
os.rm(tmp_v_file) or { panic(err) }
|
||||
assert !os.exists(tmp_v_file)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,13 +53,11 @@ fn test_all() {
|
|||
files := os.ls(dir) or { panic(err) }
|
||||
//
|
||||
wrkdir := os.join_path(os.temp_dir(), 'vtests', 'valgrind')
|
||||
os.mkdir_all(wrkdir)
|
||||
os.mkdir_all(wrkdir) or { panic(err) }
|
||||
os.chdir(wrkdir)
|
||||
//
|
||||
tests := vtest.filter_vtest_only(files.filter(it.ends_with('.v') && !it.ends_with('_test.v')),
|
||||
|
||||
basepath: valgrind_test_path
|
||||
)
|
||||
only_ordinary_v_files := files.filter(it.ends_with('.v') && !it.ends_with('_test.v'))
|
||||
tests := vtest.filter_vtest_only(only_ordinary_v_files, basepath: valgrind_test_path)
|
||||
bench.set_total_expected_steps(tests.len)
|
||||
for test in tests {
|
||||
bench.step()
|
||||
|
|
|
@ -63,10 +63,10 @@ pub fn color_compare_strings(diff_cmd string, expected string, found string) str
|
|||
ctime := time.sys_mono_now()
|
||||
e_file := os.join_path(cdir, '${ctime}.expected.txt')
|
||||
f_file := os.join_path(cdir, '${ctime}.found.txt')
|
||||
os.write_file(e_file, expected)
|
||||
os.write_file(f_file, found)
|
||||
os.write_file(e_file, expected) or { panic(err) }
|
||||
os.write_file(f_file, found) or { panic(err) }
|
||||
res := color_compare_files(diff_cmd, e_file, f_file)
|
||||
os.rm(e_file)
|
||||
os.rm(f_file)
|
||||
os.rm(e_file) or { panic(err) }
|
||||
os.rm(f_file) or { panic(err) }
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ pub fn get_vtmp_folder() string {
|
|||
}
|
||||
vtmp = os.join_path(os.temp_dir(), 'v')
|
||||
if !os.exists(vtmp) || !os.is_dir(vtmp) {
|
||||
os.mkdir_all(vtmp)
|
||||
os.mkdir_all(vtmp) or { panic(err) }
|
||||
}
|
||||
os.setenv('VTMP', vtmp, true)
|
||||
return vtmp
|
||||
|
|
|
@ -40,13 +40,13 @@ pub fn new_cache_manager(opts []string) CacheManager {
|
|||
vcache_basepath = os.join_path(os.vmodules_dir(), 'cache')
|
||||
}
|
||||
if !os.is_dir(vcache_basepath) {
|
||||
os.mkdir_all(vcache_basepath)
|
||||
os.mkdir_all(vcache_basepath) or { panic(err) }
|
||||
readme_content := 'This folder contains cached build artifacts from the V build system.
|
||||
|You can safely delete it, if it is getting too large.
|
||||
|It will be recreated the next time you compile something with V.
|
||||
|You can change its location with the VCACHE environment variable.
|
||||
'.strip_margin()
|
||||
os.write_file(os.join_path(vcache_basepath, 'README.md'), readme_content)
|
||||
os.write_file(os.join_path(vcache_basepath, 'README.md'), readme_content) or { panic(err) }
|
||||
}
|
||||
original_vopts := opts.join('|')
|
||||
return CacheManager{
|
||||
|
@ -74,7 +74,7 @@ pub fn (mut cm CacheManager) key2cpath(key string) string {
|
|||
cprefix_folder := os.join_path(cm.basepath, prefix)
|
||||
cpath = os.join_path(cprefix_folder, khash)
|
||||
if !os.is_dir(cprefix_folder) {
|
||||
os.mkdir_all(cprefix_folder)
|
||||
os.mkdir_all(cprefix_folder) or { panic(err) }
|
||||
os.chmod(cprefix_folder, 0o777)
|
||||
}
|
||||
cm.k2cpath[key] = cpath
|
||||
|
|
|
@ -17,7 +17,7 @@ fn check_cache_entry_fpath_invariants(x string, extension string) {
|
|||
fn testsuite_begin() {
|
||||
os.setenv('VCACHE', vcache_folder, true)
|
||||
// eprintln('testsuite_begin, vcache_folder = $vcache_folder')
|
||||
os.rmdir_all(vcache_folder)
|
||||
os.rmdir_all(vcache_folder) or { }
|
||||
vcache.new_cache_manager([])
|
||||
assert os.is_dir(vcache_folder)
|
||||
}
|
||||
|
@ -54,33 +54,25 @@ fn test_different_options_should_produce_different_cache_entries_for_same_key_an
|
|||
|
||||
fn test_exists() {
|
||||
mut cm := vcache.new_cache_manager([])
|
||||
cm.exists('.o', 'abc') or {
|
||||
assert true
|
||||
}
|
||||
cm.exists('.o', 'abc') or { assert true }
|
||||
//
|
||||
x := cm.save('.x', 'abc', '') or {
|
||||
assert false
|
||||
''
|
||||
}
|
||||
cm.exists('.o', 'abc') or {
|
||||
assert true
|
||||
}
|
||||
cm.exists('.o', 'abc') or { assert true }
|
||||
//
|
||||
y := cm.save('.o', 'zbc', '') or {
|
||||
assert false
|
||||
''
|
||||
}
|
||||
cm.exists('.o', 'abc') or {
|
||||
assert true
|
||||
}
|
||||
cm.exists('.o', 'abc') or { assert true }
|
||||
//
|
||||
z := cm.save('.o', 'abc', '') or {
|
||||
assert false
|
||||
''
|
||||
}
|
||||
cm.exists('.o', 'abc') or {
|
||||
assert false
|
||||
}
|
||||
cm.exists('.o', 'abc') or { assert false }
|
||||
//
|
||||
assert os.is_file(x)
|
||||
assert os.is_file(y)
|
||||
|
@ -104,6 +96,6 @@ fn test_readme_exists_and_is_readable() {
|
|||
|
||||
fn testsuite_end() {
|
||||
os.chdir(os.wd_at_startup)
|
||||
os.rmdir_all(vcache_folder)
|
||||
os.rmdir_all(vcache_folder) or { }
|
||||
assert !os.is_dir(vcache_folder)
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ fn (am AssetManager) combine(asset_type string, to_file bool) string {
|
|||
os.mkdir(am.cache_dir) or { panic(err) }
|
||||
}
|
||||
mut file := os.create(out_file) or { panic(err) }
|
||||
file.write(out.bytes())
|
||||
file.write(out.bytes()) or { panic(err) }
|
||||
file.close()
|
||||
return out_file
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import os
|
|||
// unique cache dirs are needed per test function.
|
||||
fn clean_cache_dir(dir string) {
|
||||
if os.is_dir(dir) {
|
||||
os.rmdir_all(dir)
|
||||
os.rmdir_all(dir) or { panic(err) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,10 @@ fn cache_dir(test_name string) string {
|
|||
fn get_test_file_path(file string) string {
|
||||
path := os.join_path(base_cache_dir(), file)
|
||||
if !os.is_dir(base_cache_dir()) {
|
||||
os.mkdir_all(base_cache_dir())
|
||||
os.mkdir_all(base_cache_dir()) or { panic(err) }
|
||||
}
|
||||
if !os.exists(path) {
|
||||
os.write_file(path, get_test_file_contents(file))
|
||||
os.write_file(path, get_test_file_contents(file)) or { panic(err) }
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ const (
|
|||
fn testsuite_begin() {
|
||||
os.chdir(vroot)
|
||||
if os.exists(serverexe) {
|
||||
os.rm(serverexe)
|
||||
os.rm(serverexe) or { }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ fn simple_tcp_client(config SimpleTcpClientConfig) ?string {
|
|||
client.set_read_timeout(tcp_r_timeout)
|
||||
client.set_write_timeout(tcp_w_timeout)
|
||||
defer {
|
||||
client.close()
|
||||
client.close() or { }
|
||||
}
|
||||
message := 'GET $config.path HTTP/1.1
|
||||
Host: $config.host
|
||||
|
|
|
@ -355,7 +355,8 @@ fn handle_conn<T>(mut conn net.TcpConn, mut app T) {
|
|||
//}
|
||||
// read body
|
||||
mut read_body := []byte{len: len}
|
||||
reader.read(mut read_body) // read just the amount of content len if there is no content there is nothing more to read here
|
||||
// read just the amount of content len if there is no content there is nothing more to read here
|
||||
reader.read(mut read_body) or { println('reader.read failed with err: $err') }
|
||||
body += read_body.bytestr()
|
||||
break
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module ttf
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Common data for the module
|
||||
|
@ -15,8 +16,7 @@ import os
|
|||
import math
|
||||
|
||||
// text align
|
||||
pub
|
||||
enum Text_align {
|
||||
pub enum Text_align {
|
||||
left
|
||||
center
|
||||
right
|
||||
|
@ -24,8 +24,7 @@ enum Text_align {
|
|||
}
|
||||
|
||||
// draw style
|
||||
pub
|
||||
enum Style {
|
||||
pub enum Style {
|
||||
outline
|
||||
outline_aliased
|
||||
filled
|
||||
|
@ -38,8 +37,9 @@ enum Style {
|
|||
*
|
||||
******************************************************************************/
|
||||
const debug_flag = false
|
||||
fn dprintln(txt string){
|
||||
if debug_flag {
|
||||
|
||||
fn dprintln(txt string) {
|
||||
if ttf.debug_flag {
|
||||
println(txt)
|
||||
}
|
||||
}
|
||||
|
@ -50,34 +50,34 @@ fn dprintln(txt string){
|
|||
*
|
||||
******************************************************************************/
|
||||
// transform the bitmap from one layer to color layers
|
||||
fn (mut bmp BitMap) format_texture(){
|
||||
fn (mut bmp BitMap) format_texture() {
|
||||
r := byte(bmp.color >> 24)
|
||||
g := byte((bmp.color >> 16) & 0xFF)
|
||||
b := byte((bmp.color >> 8 ) & 0xFF)
|
||||
b := byte((bmp.color >> 8) & 0xFF)
|
||||
a := byte(bmp.color & 0xFF)
|
||||
|
||||
b_r := byte(bmp.bg_color >> 24)
|
||||
b_g := byte((bmp.bg_color >> 16) & 0xFF)
|
||||
b_b := byte((bmp.bg_color >> 8 ) & 0xFF)
|
||||
b_b := byte((bmp.bg_color >> 8) & 0xFF)
|
||||
b_a := byte(bmp.bg_color & 0xFF)
|
||||
|
||||
// trasform buffer in a texture
|
||||
x := byteptr(bmp.buf)
|
||||
unsafe{
|
||||
unsafe {
|
||||
mut i := 0
|
||||
for i<bmp.buf_size {
|
||||
for i < bmp.buf_size {
|
||||
data := x[i]
|
||||
if data > 0 {
|
||||
x[i+0] = r
|
||||
x[i+1] = g
|
||||
x[i+2] = b
|
||||
x[i + 0] = r
|
||||
x[i + 1] = g
|
||||
x[i + 2] = b
|
||||
// alpha
|
||||
x[i+3] = byte((a * data) >> 8)
|
||||
x[i + 3] = byte((a * data) >> 8)
|
||||
} else {
|
||||
x[i+0] = b_r
|
||||
x[i+1] = b_g
|
||||
x[i+2] = b_b
|
||||
x[i+3] = b_a
|
||||
x[i + 0] = b_r
|
||||
x[i + 1] = b_g
|
||||
x[i + 2] = b_b
|
||||
x[i + 3] = b_a
|
||||
}
|
||||
i += 4
|
||||
}
|
||||
|
@ -85,8 +85,7 @@ fn (mut bmp BitMap) format_texture(){
|
|||
}
|
||||
|
||||
// write out a .ppm file
|
||||
pub
|
||||
fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||
pub fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
||||
tmp_buf := bmp.buf
|
||||
mut buf := malloc(bmp.buf_size)
|
||||
unsafe { C.memcpy(buf, tmp_buf, bmp.buf_size) }
|
||||
|
@ -95,18 +94,17 @@ fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
|||
bmp.format_texture()
|
||||
npixels := bmp.width * bmp.height
|
||||
mut f_out := os.create(file_name) or { panic(err) }
|
||||
f_out.writeln('P3')
|
||||
f_out.writeln('${bmp.width} ${bmp.height}')
|
||||
f_out.writeln('255')
|
||||
for i in 0..npixels {
|
||||
f_out.writeln('P3') or { panic(err) }
|
||||
f_out.writeln('$bmp.width $bmp.height') or { panic(err) }
|
||||
f_out.writeln('255') or { panic(err) }
|
||||
for i in 0 .. npixels {
|
||||
pos := i * bmp.bp
|
||||
unsafe {
|
||||
c_r := bmp.buf[pos]
|
||||
c_g := bmp.buf[pos +1 ]
|
||||
c_g := bmp.buf[pos + 1]
|
||||
c_b := bmp.buf[pos + 2]
|
||||
f_out.write_str('${c_r} ${c_g} ${c_b} ')
|
||||
f_out.write_str('$c_r $c_g $c_b ') or { panic(err) }
|
||||
}
|
||||
|
||||
}
|
||||
f_out.close()
|
||||
|
||||
|
@ -114,23 +112,22 @@ fn (mut bmp BitMap) save_as_ppm(file_name string) {
|
|||
bmp.buf = tmp_buf
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) get_raw_bytes() []byte {
|
||||
mut f_buf := []byte{len: bmp.buf_size/4}
|
||||
mut i:=0
|
||||
pub fn (mut bmp BitMap) get_raw_bytes() []byte {
|
||||
mut f_buf := []byte{len: bmp.buf_size / 4}
|
||||
mut i := 0
|
||||
for i < bmp.buf_size {
|
||||
unsafe { f_buf[i>>2] = *(bmp.buf + i) }
|
||||
unsafe {
|
||||
f_buf[i >> 2] = *(bmp.buf + i)
|
||||
}
|
||||
i += 4
|
||||
}
|
||||
return f_buf
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) save_raw_data(file_name string) {
|
||||
os.write_file_array(file_name, bmp.get_raw_bytes())
|
||||
pub fn (mut bmp BitMap) save_raw_data(file_name string) {
|
||||
os.write_file_array(file_name, bmp.get_raw_bytes()) or { panic(err) }
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Math functions
|
||||
//
|
||||
|
@ -181,8 +178,7 @@ fn rfpart(x f32) f32 {
|
|||
******************************************************************************/
|
||||
/*
|
||||
[inline]
|
||||
pub
|
||||
fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
||||
pub fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
||||
if x < 0 || x >= dev.width || y < 0 || y >= dev.height {
|
||||
return 0,0,0,0
|
||||
}
|
||||
|
@ -193,8 +189,7 @@ fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
|
|||
}
|
||||
|
||||
[inline]
|
||||
pub
|
||||
fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
||||
pub fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
||||
r, g, b, a := dev.get_color(x, y)
|
||||
unsafe{
|
||||
return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a)
|
||||
|
@ -207,18 +202,16 @@ fn (mut dev BitMap) get_color_u32(x int, y int) u32{
|
|||
*
|
||||
******************************************************************************/
|
||||
[inline]
|
||||
pub
|
||||
fn color_multiply_alpha(c u32, level f32) u32 {
|
||||
return u32(f32( c & 0xFF) * level)
|
||||
pub fn color_multiply_alpha(c u32, level f32) u32 {
|
||||
return u32(f32(c & 0xFF) * level)
|
||||
}
|
||||
|
||||
[inline]
|
||||
pub
|
||||
fn color_multiply(c u32, level f32) u32 {
|
||||
mut r := (f32((c >> 24) & 0xFF)/255.0) * level
|
||||
mut g := (f32((c >> 16) & 0xFF)/255.0) * level
|
||||
mut b := (f32((c >> 8) & 0xFF)/255.0) * level
|
||||
mut a := (f32( c & 0xFF)/255.0) * level
|
||||
pub fn color_multiply(c u32, level f32) u32 {
|
||||
mut r := (f32((c >> 24) & 0xFF) / 255.0) * level
|
||||
mut g := (f32((c >> 16) & 0xFF) / 255.0) * level
|
||||
mut b := (f32((c >> 8) & 0xFF) / 255.0) * level
|
||||
mut a := (f32(c & 0xFF) / 255.0) * level
|
||||
r = if r > 1.0 { 1.0 } else { r }
|
||||
g = if g > 1.0 { 1.0 } else { g }
|
||||
b = if b > 1.0 { 1.0 } else { b }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module ttf
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* BMP render module utility functions
|
||||
|
@ -15,40 +16,31 @@ module ttf
|
|||
import encoding.utf8
|
||||
import math
|
||||
|
||||
pub
|
||||
struct BitMap {
|
||||
pub struct BitMap {
|
||||
pub mut:
|
||||
tf &TTF_File
|
||||
|
||||
buf byteptr // pointer to the memory buffer
|
||||
buf_size int // allocated buf size in bytes
|
||||
|
||||
width int =1 // width of the buffer
|
||||
height int =1 // height of the buffer
|
||||
bp int =4 // byte per pixel of the buffer
|
||||
|
||||
width int = 1 // width of the buffer
|
||||
height int = 1 // height of the buffer
|
||||
bp int = 4 // byte per pixel of the buffer
|
||||
bg_color u32 = 0xFFFFFF_00 // background RGBA format
|
||||
color u32 = 0x000000_FF // RGBA format
|
||||
scale f32 = 1.0 // internal usage!!
|
||||
scale_x f32 = 1.0 // X scale of the single glyph
|
||||
scale_y f32 = 1.0 // Y scale of the single glyph
|
||||
angle f32 = 0.0 // angle of rotation of the bitmap
|
||||
|
||||
// spaces
|
||||
space_cw f32 = 1.0 // width of the space glyph internal usage!!
|
||||
space_mult f32 = f32(0.0) //1.0/16.0 // space between letter, is a multiplier for a standrd space ax
|
||||
|
||||
space_mult f32 = f32(0.0) // 1.0/16.0 // space between letter, is a multiplier for a standrd space ax
|
||||
// used only by internal text rendering!!
|
||||
tr_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // transformation matrix
|
||||
ch_matrix []f32 = [f32(1), 0, 0, 0, 1, 0, 0, 0, 0] // character matrix
|
||||
|
||||
style Style = .filled // default syle
|
||||
align Text_align = .left // default text align
|
||||
justify bool // justify text flag, default deactivated
|
||||
justify_fill_ratio f32 = 0.5 // justify fill ratio, if the ratio of the filled row is >= of this then justify the text
|
||||
|
||||
filler [][]int // filler buffer for the renderer
|
||||
|
||||
// flag to force font embedded metrics
|
||||
use_font_metrics bool
|
||||
}
|
||||
|
@ -59,8 +51,7 @@ pub mut:
|
|||
*
|
||||
******************************************************************************/
|
||||
// clear clear the bitmap with 0 bytes
|
||||
pub
|
||||
fn (mut bmp BitMap) clear() {
|
||||
pub fn (mut bmp BitMap) clear() {
|
||||
mut sz := bmp.width * bmp.height * bmp.bp
|
||||
unsafe {
|
||||
C.memset(bmp.buf, 0x00, sz)
|
||||
|
@ -69,30 +60,28 @@ fn (mut bmp BitMap) clear() {
|
|||
|
||||
// transform matrix applied to the text
|
||||
fn (bmp &BitMap) trf_txt(p &Point) (int, int) {
|
||||
return int(p.x * bmp.tr_matrix[0] + p.y * bmp.tr_matrix[3] + bmp.tr_matrix[6]),
|
||||
int(p.x * bmp.tr_matrix[1] + p.y * bmp.tr_matrix[4] + bmp.tr_matrix[7])
|
||||
return int(p.x * bmp.tr_matrix[0] + p.y * bmp.tr_matrix[3] + bmp.tr_matrix[6]), int(
|
||||
p.x * bmp.tr_matrix[1] + p.y * bmp.tr_matrix[4] + bmp.tr_matrix[7])
|
||||
}
|
||||
|
||||
// transform matrix applied to the char
|
||||
fn (bmp &BitMap) trf_ch(p &Point) (int, int) {
|
||||
return int(p.x * bmp.ch_matrix[0] + p.y * bmp.ch_matrix[3] + bmp.ch_matrix[6]),
|
||||
int(p.x * bmp.ch_matrix[1] + p.y * bmp.ch_matrix[4] + bmp.ch_matrix[7])
|
||||
return int(p.x * bmp.ch_matrix[0] + p.y * bmp.ch_matrix[3] + bmp.ch_matrix[6]), int(
|
||||
p.x * bmp.ch_matrix[1] + p.y * bmp.ch_matrix[4] + bmp.ch_matrix[7])
|
||||
}
|
||||
|
||||
// set draw postion in the buffer
|
||||
pub
|
||||
fn (mut bmp BitMap) set_pos(x f32, y f32) {
|
||||
pub fn (mut bmp BitMap) set_pos(x f32, y f32) {
|
||||
bmp.tr_matrix[6] = x
|
||||
bmp.tr_matrix[7] = y
|
||||
}
|
||||
|
||||
// set the rotation angle in radiants
|
||||
pub
|
||||
fn (mut bmp BitMap) set_rotation(a f32) {
|
||||
bmp.tr_matrix[0] = f32(math.cos(a)) //1
|
||||
bmp.tr_matrix[1] = f32(-math.sin(a)) //0
|
||||
bmp.tr_matrix[3] = f32(math.sin(a)) //0
|
||||
bmp.tr_matrix[4] = f32(math.cos(a)) //1
|
||||
pub fn (mut bmp BitMap) set_rotation(a f32) {
|
||||
bmp.tr_matrix[0] = f32(math.cos(a)) // 1
|
||||
bmp.tr_matrix[1] = f32(-math.sin(a)) // 0
|
||||
bmp.tr_matrix[3] = f32(math.sin(a)) // 0
|
||||
bmp.tr_matrix[4] = f32(math.cos(a)) // 1
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -100,43 +89,40 @@ fn (mut bmp BitMap) set_rotation(a f32) {
|
|||
* Filler functions
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (mut bmp BitMap) init_filler() {
|
||||
pub fn (mut bmp BitMap) init_filler() {
|
||||
h := bmp.height - bmp.filler.len
|
||||
if h < 1 {
|
||||
return
|
||||
}
|
||||
for _ in 0..h {
|
||||
bmp.filler << []int{len:4}
|
||||
for _ in 0 .. h {
|
||||
bmp.filler << []int{len: 4}
|
||||
}
|
||||
// dprintln("Init filler: ${bmp.filler.len} rows")
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) clear_filler() {
|
||||
for i in 0..bmp.height {
|
||||
pub fn (mut bmp BitMap) clear_filler() {
|
||||
for i in 0 .. bmp.height {
|
||||
bmp.filler[i].clear()
|
||||
}
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) exec_filler() {
|
||||
for y in 0..bmp.height {
|
||||
pub fn (mut bmp BitMap) exec_filler() {
|
||||
for y in 0 .. bmp.height {
|
||||
if bmp.filler[y].len > 0 {
|
||||
bmp.filler[y].sort()
|
||||
if bmp.filler[y].len & 1 != 0 {
|
||||
//dprintln("even line!! $y => ${bmp.filler[y]}")
|
||||
// dprintln("even line!! $y => ${bmp.filler[y]}")
|
||||
continue
|
||||
}
|
||||
mut index := 0
|
||||
for index < bmp.filler[y].len {
|
||||
startx := bmp.filler[y][index] + 1
|
||||
endx := bmp.filler[y][index+1]
|
||||
endx := bmp.filler[y][index + 1]
|
||||
if startx >= endx {
|
||||
index += 2
|
||||
continue
|
||||
}
|
||||
for x in startx..endx {
|
||||
for x in startx .. endx {
|
||||
bmp.plot(x, y, bmp.color)
|
||||
}
|
||||
index += 2
|
||||
|
@ -145,8 +131,7 @@ fn (mut bmp BitMap) exec_filler() {
|
|||
}
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
pub fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
mut x0 := f32(in_x0)
|
||||
mut x1 := f32(in_x1)
|
||||
mut y0 := f32(in_y0)
|
||||
|
@ -184,15 +169,15 @@ fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
return
|
||||
}
|
||||
mut n := dx / dy
|
||||
for y in 0..int(dy+0.5) {
|
||||
for y in 0 .. int(dy + 0.5) {
|
||||
yd := int(y + y0)
|
||||
x := n * y + x0
|
||||
if x > bmp.width || yd >= bmp.filler.len {
|
||||
break
|
||||
}
|
||||
if yd >= 0 && yd < bmp.filler.len {
|
||||
bmp.filler[yd] << int(x+0.5)
|
||||
//bmp.plot(int(x+0.5), yd, bmp.color)
|
||||
bmp.filler[yd] << int(x + 0.5)
|
||||
// bmp.plot(int(x+0.5), yd, bmp.color)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,23 +188,22 @@ fn (mut bmp BitMap) fline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
*
|
||||
******************************************************************************/
|
||||
[inline]
|
||||
pub
|
||||
fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
||||
pub fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
||||
if x < 0 || x >= bmp.width || y < 0 || y >= bmp.height {
|
||||
return false
|
||||
}
|
||||
mut index := (x + y * bmp.width) * bmp.bp
|
||||
unsafe {
|
||||
//bmp.buf[index]=0xFF
|
||||
// bmp.buf[index]=0xFF
|
||||
bmp.buf[index] = byte(c & 0xFF) // write only the alpha
|
||||
}
|
||||
/*
|
||||
/*
|
||||
for count in 0..(bmp.bp) {
|
||||
unsafe{
|
||||
bmp.buf[index + count] = byte((c >> (bmp.bp - count - 1) * 8) & 0x0000_00FF)
|
||||
}
|
||||
}
|
||||
*/
|
||||
*/
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -229,9 +213,8 @@ fn (mut bmp BitMap) plot(x int, y int, c u32) bool {
|
|||
*
|
||||
******************************************************************************/
|
||||
// aline draw an aliased line on the bitmap
|
||||
pub
|
||||
fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
//mut c1 := c
|
||||
pub fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
// mut c1 := c
|
||||
mut x0 := f32(in_x0)
|
||||
mut x1 := f32(in_x1)
|
||||
mut y0 := f32(in_y0)
|
||||
|
@ -263,11 +246,11 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
mut x := x0
|
||||
for x <= x1 + 0.5 {
|
||||
y := m * (x - x0) + y0
|
||||
e := 1-fabs(y-0.5-int(y))
|
||||
bmp.plot(int(x), int(y), color_multiply_alpha(c, e*0.75))
|
||||
e := 1 - fabs(y - 0.5 - int(y))
|
||||
bmp.plot(int(x), int(y), color_multiply_alpha(c, e * 0.75))
|
||||
|
||||
ys1 := y + dist
|
||||
if int(ys1) != int(y){
|
||||
if int(ys1) != int(y) {
|
||||
v1 := fabs(ys1 - y) / dist * (1 - e)
|
||||
bmp.plot(int(x), int(ys1), color_multiply_alpha(c, v1))
|
||||
}
|
||||
|
@ -280,7 +263,6 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
|
||||
x += 1.0
|
||||
}
|
||||
|
||||
} else {
|
||||
if y1 < y0 {
|
||||
tmp = x0
|
||||
|
@ -302,7 +284,7 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
for y <= y1 + 0.5 {
|
||||
x := n * (y - y0) + x0
|
||||
e := f32(1 - fabs(x - 0.5 - int(x)))
|
||||
bmp.plot(int(x), int(y), color_multiply_alpha(c, f32(e*0.75)))
|
||||
bmp.plot(int(x), int(y), color_multiply_alpha(c, f32(e * 0.75)))
|
||||
|
||||
xs1 := x + dist
|
||||
if int(xs1) != int(x) {
|
||||
|
@ -325,9 +307,7 @@ fn (mut bmp BitMap) aline(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
* draw functions
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
|
||||
pub fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
// outline with aliased borders
|
||||
if bmp.style == .outline_aliased {
|
||||
bmp.aline(in_x0, in_y0, in_x1, in_y1, c)
|
||||
|
@ -350,7 +330,7 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
x1 := int(in_x1)
|
||||
y0 := int(in_y0)
|
||||
y1 := int(in_y1)
|
||||
//dprintln("line[$x0,$y0,$x1,$y1]")
|
||||
// dprintln("line[$x0,$y0,$x1,$y1]")
|
||||
|
||||
mut x := x0
|
||||
mut y := y0
|
||||
|
@ -363,24 +343,24 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
// verical line
|
||||
if dx == 0 {
|
||||
if y0 < y1 {
|
||||
for yt in y0..y1+1 {
|
||||
for yt in y0 .. y1 + 1 {
|
||||
bmp.plot(x0, yt, c)
|
||||
}
|
||||
return
|
||||
}
|
||||
for yt in y1..y0+1 {
|
||||
for yt in y1 .. y0 + 1 {
|
||||
bmp.plot(x0, yt, c)
|
||||
}
|
||||
return
|
||||
// horizontal line
|
||||
} else if dy == 0{
|
||||
return
|
||||
} else if dy == 0 {
|
||||
if x0 < x1 {
|
||||
for xt in x0..x1+1 {
|
||||
for xt in x0 .. x1 + 1 {
|
||||
bmp.plot(xt, y0, c)
|
||||
}
|
||||
return
|
||||
}
|
||||
for xt in x1..x0+1 {
|
||||
for xt in x1 .. x0 + 1 {
|
||||
bmp.plot(xt, y0, c)
|
||||
}
|
||||
return
|
||||
|
@ -388,10 +368,10 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
|
||||
mut err := dx + dy // error value e_xy
|
||||
for {
|
||||
//bmp.plot(x, y, u32(0xFF00))
|
||||
// bmp.plot(x, y, u32(0xFF00))
|
||||
bmp.plot(x, y, c)
|
||||
|
||||
//dprintln("$x $y [$x0,$y0,$x1,$y1]")
|
||||
// dprintln("$x $y [$x0,$y0,$x1,$y1]")
|
||||
if x == x1 && y == y1 {
|
||||
break
|
||||
}
|
||||
|
@ -405,20 +385,16 @@ fn (mut bmp BitMap) line(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
|||
y += sy
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
pub fn (mut bmp BitMap) box(in_x0 int, in_y0 int, in_x1 int, in_y1 int, c u32) {
|
||||
bmp.line(in_x0, in_y0, in_x1, in_y0, c)
|
||||
bmp.line(in_x1, in_y0, in_x1, in_y1, c)
|
||||
bmp.line(in_x0, in_y1, in_x1, in_y1, c)
|
||||
bmp.line(in_x0, in_y0, in_x0, in_y1, c)
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx int, in_cy int, c u32) {
|
||||
pub fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx int, in_cy int, c u32) {
|
||||
/*
|
||||
x0 := int(in_x0 * bmp.scale)
|
||||
x1 := int(in_x1 * bmp.scale)
|
||||
|
@ -439,19 +415,19 @@ fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx
|
|||
dy := abs(y0 - y1)
|
||||
|
||||
// if few pixel draw a simple line
|
||||
//if dx == 0 && dy == 0 {
|
||||
// if dx == 0 && dy == 0 {
|
||||
if dx <= 2 || dy <= 2 {
|
||||
//bmp.plot(x0, y0, c)
|
||||
bmp.line(x0,y0,x1,y1, c)
|
||||
// bmp.plot(x0, y0, c)
|
||||
bmp.line(x0, y0, x1, y1, c)
|
||||
return
|
||||
}
|
||||
|
||||
division = 1.0/(f64( if dx>dy {dx} else {dy} ))
|
||||
division = 1.0 / (f64(if dx > dy { dx } else { dy }))
|
||||
|
||||
//division = 0.1 // 10 division
|
||||
//division = 0.25 // 4 division
|
||||
// division = 0.1 // 10 division
|
||||
// division = 0.25 // 4 division
|
||||
|
||||
//dprintln("div: $division")
|
||||
// dprintln("div: $division")
|
||||
|
||||
/*
|
||||
----- Bezier quadratic form -----
|
||||
|
@ -465,13 +441,13 @@ fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx
|
|||
mut y_old := y0
|
||||
mut t := 0.0
|
||||
|
||||
for t <= (1.0 + division/2.0){
|
||||
for t <= (1.0 + division / 2.0) {
|
||||
s := 1.0 - t
|
||||
x := s * s * x0 + 2.0 * s * t * cx + t * t * x1
|
||||
y := s * s * y0 + 2.0 * s * t * cy + t * t * y1
|
||||
xi := int(x + 0.5)
|
||||
yi := int(y + 0.5)
|
||||
//bmp.plot(xi, yi, c)
|
||||
// bmp.plot(xi, yi, c)
|
||||
bmp.line(x_old, y_old, xi, yi, c)
|
||||
x_old = xi
|
||||
y_old = yi
|
||||
|
@ -484,8 +460,7 @@ fn (mut bmp BitMap) quadratic(in_x0 int, in_y0 int, in_x1 int, in_y1 int, in_cx
|
|||
* TTF Query functions
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
||||
pub fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
||||
mut res := []int{}
|
||||
mut w := 0
|
||||
|
||||
|
@ -505,12 +480,11 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
|||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// manage unicode chars like latin greek etc
|
||||
c_len := ((0xe5000000>>((char>>3) & 0x1e)) & 3) + 1
|
||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||
if c_len > 1 {
|
||||
tmp_char := utf8.get_uchar(in_string,i)
|
||||
//dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
tmp_char := utf8.get_uchar(in_string, i)
|
||||
// dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
char = u16(tmp_char)
|
||||
}
|
||||
|
||||
|
@ -522,18 +496,18 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
|||
continue
|
||||
}
|
||||
|
||||
ax , ay := bmp.tf.next_kern(c_index)
|
||||
//dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
ax, ay := bmp.tf.next_kern(c_index)
|
||||
// dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
|
||||
//cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
//dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
// cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
// dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
|
||||
//----- Calc Glyph transformations -----
|
||||
mut x0 := w + int(ax * bmp.scale)
|
||||
mut y0 := 0 + int(ay * bmp.scale)
|
||||
|
||||
p := Point{x0,y0,false}
|
||||
x1 , y1 := bmp.trf_txt(p)
|
||||
p := Point{x0, y0, false}
|
||||
x1, y1 := bmp.trf_txt(p)
|
||||
// init ch_matrix
|
||||
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
|
||||
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
|
||||
|
@ -542,24 +516,23 @@ fn (mut bmp BitMap) get_chars_bbox(in_string string) []int {
|
|||
bmp.ch_matrix[6] = int(x1)
|
||||
bmp.ch_matrix[7] = int(y1)
|
||||
|
||||
//x_min, x_max, y_min, y_max := bmp.tf.read_glyph_dim(c_index)
|
||||
// x_min, x_max, y_min, y_max := bmp.tf.read_glyph_dim(c_index)
|
||||
x_min, x_max, _, _ := bmp.tf.read_glyph_dim(c_index)
|
||||
//-----------------
|
||||
|
||||
width := int( (abs(x_max + x_min) + ax) * bmp.scale)
|
||||
//width := int((cw+ax) * bmp.scale)
|
||||
width := int((abs(x_max + x_min) + ax) * bmp.scale)
|
||||
// width := int((cw+ax) * bmp.scale)
|
||||
w += width + div_space_cw
|
||||
h := int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||
res << w
|
||||
res << h
|
||||
|
||||
i+= c_len
|
||||
i += c_len
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
||||
pub fn (mut bmp BitMap) get_bbox(in_string string) (int, int) {
|
||||
mut w := 0
|
||||
|
||||
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
||||
|
@ -578,12 +551,11 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
|||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// manage unicode chars like latin greek etc
|
||||
c_len := ((0xe5000000>>((char>>3) & 0x1e)) & 3) + 1
|
||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||
if c_len > 1 {
|
||||
tmp_char := utf8.get_uchar(in_string,i)
|
||||
//dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
tmp_char := utf8.get_uchar(in_string, i)
|
||||
// dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
char = u16(tmp_char)
|
||||
}
|
||||
|
||||
|
@ -594,18 +566,18 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
|||
i += c_len
|
||||
continue
|
||||
}
|
||||
ax , ay := bmp.tf.next_kern(c_index)
|
||||
//dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
ax, ay := bmp.tf.next_kern(c_index)
|
||||
// dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
|
||||
//cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
//dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
// cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
// dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
|
||||
//----- Calc Glyph transformations -----
|
||||
mut x0 := w + int(ax * bmp.scale)
|
||||
mut y0 := 0 + int(ay * bmp.scale)
|
||||
|
||||
p := Point{x0,y0,false}
|
||||
x1 , y1 := bmp.trf_txt(p)
|
||||
p := Point{x0, y0, false}
|
||||
x1, y1 := bmp.trf_txt(p)
|
||||
// init ch_matrix
|
||||
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
|
||||
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
|
||||
|
@ -615,20 +587,20 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
|||
bmp.ch_matrix[7] = int(y1)
|
||||
|
||||
x_min, x_max, _, _ := bmp.tf.read_glyph_dim(c_index)
|
||||
//x_min := 1
|
||||
//x_max := 2
|
||||
// x_min := 1
|
||||
// x_max := 2
|
||||
//-----------------
|
||||
|
||||
width := int( (abs(x_max + x_min) + ax) * bmp.scale)
|
||||
//width := int((cw+ax) * bmp.scale)
|
||||
width := int((abs(x_max + x_min) + ax) * bmp.scale)
|
||||
// width := int((cw+ax) * bmp.scale)
|
||||
w += width + div_space_cw
|
||||
|
||||
i+= c_len
|
||||
i += c_len
|
||||
}
|
||||
|
||||
//dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}")
|
||||
//buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) )
|
||||
return w , int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||
// dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}")
|
||||
// buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) )
|
||||
return w, int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -638,7 +610,7 @@ fn (mut bmp BitMap) get_bbox(in_string string) (int, int){
|
|||
******************************************************************************/
|
||||
fn (mut bmp BitMap) draw_notdef_glyph(in_x int, in_w int) {
|
||||
mut p := Point{in_x, 0, false}
|
||||
x1 , y1 := bmp.trf_txt(p)
|
||||
x1, y1 := bmp.trf_txt(p)
|
||||
// init ch_matrix
|
||||
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
|
||||
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
|
||||
|
@ -646,17 +618,16 @@ fn (mut bmp BitMap) draw_notdef_glyph(in_x int, in_w int) {
|
|||
bmp.ch_matrix[4] = bmp.tr_matrix[4] * -bmp.scale * bmp.scale_y
|
||||
bmp.ch_matrix[6] = int(x1)
|
||||
bmp.ch_matrix[7] = int(y1)
|
||||
x,y := bmp.trf_ch(p)
|
||||
x, y := bmp.trf_ch(p)
|
||||
|
||||
y_h := fabs(bmp.tf.y_max-bmp.tf.y_min)* bmp.scale * 0.5
|
||||
y_h := fabs(bmp.tf.y_max - bmp.tf.y_min) * bmp.scale * 0.5
|
||||
|
||||
bmp.box(int(x), int(y), int(x - in_w), int(y - y_h), bmp.color)
|
||||
bmp.line(int(x), int(y), int(x - in_w ), int(y - y_h), bmp.color)
|
||||
bmp.line(int(x - in_w ), int(y), int(x), int(y - y_h), bmp.color)
|
||||
bmp.line(int(x), int(y), int(x - in_w), int(y - y_h), bmp.color)
|
||||
bmp.line(int(x - in_w), int(y), int(x), int(y - y_h), bmp.color)
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
||||
pub fn (mut bmp BitMap) draw_text(in_string string) (int, int) {
|
||||
mut w := 0
|
||||
|
||||
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
||||
|
@ -675,12 +646,11 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
|||
i++
|
||||
continue
|
||||
}
|
||||
|
||||
// manage unicode chars like latin greek etc
|
||||
c_len := ((0xe5000000>>((char>>3) & 0x1e)) & 3) + 1
|
||||
c_len := ((0xe5000000 >> ((char >> 3) & 0x1e)) & 3) + 1
|
||||
if c_len > 1 {
|
||||
tmp_char := utf8.get_uchar(in_string,i)
|
||||
//dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
tmp_char := utf8.get_uchar(in_string, i)
|
||||
// dprintln("tmp_char: ${tmp_char.hex()}")
|
||||
char = u16(tmp_char)
|
||||
}
|
||||
|
||||
|
@ -693,19 +663,19 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
|||
continue
|
||||
}
|
||||
|
||||
ax , ay := bmp.tf.next_kern(c_index)
|
||||
//dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
ax, ay := bmp.tf.next_kern(c_index)
|
||||
// dprintln("char_index: $c_index ax: $ax ay: $ay")
|
||||
|
||||
cw, _ := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
//cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
//dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
// cw, lsb := bmp.tf.get_horizontal_metrics(u16(char))
|
||||
// dprintln("metrics: [${u16(char):c}] cw:$cw lsb:$lsb")
|
||||
|
||||
//----- Draw_Glyph transformations -----
|
||||
mut x0 := w + int(ax * bmp.scale)
|
||||
mut y0 := 0 + int(ay * bmp.scale)
|
||||
|
||||
p := Point{x0,y0,false}
|
||||
x1 , y1 := bmp.trf_txt(p)
|
||||
p := Point{x0, y0, false}
|
||||
x1, y1 := bmp.trf_txt(p)
|
||||
// init ch_matrix
|
||||
bmp.ch_matrix[0] = bmp.tr_matrix[0] * bmp.scale * bmp.scale_x
|
||||
bmp.ch_matrix[1] = bmp.tr_matrix[1] * bmp.scale * bmp.scale_x
|
||||
|
@ -719,21 +689,20 @@ fn (mut bmp BitMap) draw_text(in_string string) (int, int){
|
|||
// x_max := 2
|
||||
//-----------------
|
||||
|
||||
mut width := int( (abs(x_max + x_min) + ax) * bmp.scale)
|
||||
mut width := int((abs(x_max + x_min) + ax) * bmp.scale)
|
||||
if bmp.use_font_metrics {
|
||||
width = int((cw+ax) * bmp.scale)
|
||||
width = int((cw + ax) * bmp.scale)
|
||||
}
|
||||
w += width + div_space_cw
|
||||
i+= c_len
|
||||
i += c_len
|
||||
}
|
||||
|
||||
//dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}")
|
||||
//buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) )
|
||||
return w , int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||
// dprintln("y_min: $bmp.tf.y_min y_max: $bmp.tf.y_max res: ${int((bmp.tf.y_max - bmp.tf.y_min)*buf.scale)} width: ${int( (cw) * buf.scale)}")
|
||||
// buf.box(0,y_base - int((bmp.tf.y_min)*buf.scale), int( (x_max) * buf.scale), y_base-int((bmp.tf.y_max)*buf.scale), u32(0xFF00_0000) )
|
||||
return w, int(abs(int(bmp.tf.y_max - bmp.tf.y_min)) * bmp.scale)
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
||||
pub fn (mut bmp BitMap) draw_glyph(index u16) (int, int) {
|
||||
glyph := bmp.tf.read_glyph(index)
|
||||
|
||||
if !glyph.valid_glyph {
|
||||
|
@ -749,20 +718,20 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
|||
mut contour_start := 0
|
||||
mut x0 := 0
|
||||
mut y0 := 0
|
||||
color := bmp.color //u32(0xFFFF_FF00) // RGBA white
|
||||
//color1 := u32(0xFF00_0000) // RGBA red
|
||||
//color2 := u32(0x00FF_0000) // RGBA green
|
||||
color := bmp.color // u32(0xFFFF_FF00) // RGBA white
|
||||
// color1 := u32(0xFF00_0000) // RGBA red
|
||||
// color2 := u32(0x00FF_0000) // RGBA green
|
||||
|
||||
mut sp_x := 0
|
||||
mut sp_y := 0
|
||||
mut point := Point{}
|
||||
|
||||
for count, point_raw in glyph.points {
|
||||
//dprintln("count: $count, state: $s pl:$glyph.points.len")
|
||||
// dprintln("count: $count, state: $s pl:$glyph.points.len")
|
||||
point.x = point_raw.x
|
||||
point.y = point_raw.y
|
||||
|
||||
point.x , point.y = bmp.trf_ch(point)
|
||||
point.x, point.y = bmp.trf_ch(point)
|
||||
point.on_curve = point_raw.on_curve
|
||||
|
||||
if s == 0 {
|
||||
|
@ -775,69 +744,67 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
|||
} else if s == 1 {
|
||||
if point.on_curve {
|
||||
bmp.line(x0, y0, point.x, point.y, color)
|
||||
//bmp.aline(x0, y0, point.x, point.y, u32(0xFFFF0000))
|
||||
// bmp.aline(x0, y0, point.x, point.y, u32(0xFFFF0000))
|
||||
x0 = point.x
|
||||
y0 = point.y
|
||||
} else {
|
||||
s = 2
|
||||
}
|
||||
|
||||
} else {
|
||||
//dprintln("s==2")
|
||||
// dprintln("s==2")
|
||||
mut prev := glyph.points[count - 1]
|
||||
prev.x, prev.y = bmp.trf_ch(prev)
|
||||
if point.on_curve {
|
||||
//dprintln("HERE1")
|
||||
// dprintln("HERE1")
|
||||
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,point.x + x, point.y + y);
|
||||
//bmp.line(x0, y0, point.x + in_x, point.y + in_y, color1)
|
||||
//bmp.quadratic(x0, y0, point.x + in_x, point.y + in_y, prev.x + in_x, prev.y + in_y, u32(0xa0a00000))
|
||||
// bmp.line(x0, y0, point.x + in_x, point.y + in_y, color1)
|
||||
// bmp.quadratic(x0, y0, point.x + in_x, point.y + in_y, prev.x + in_x, prev.y + in_y, u32(0xa0a00000))
|
||||
bmp.quadratic(x0, y0, point.x, point.y, prev.x, prev.y, color)
|
||||
x0 = point.x
|
||||
y0 = point.y
|
||||
s = 1
|
||||
} else {
|
||||
//dprintln("HERE2")
|
||||
// dprintln("HERE2")
|
||||
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||
// (prev.x + point.x) / 2 + x,
|
||||
// (prev.y + point.y) / 2 + y);
|
||||
|
||||
//bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2)
|
||||
//bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2)
|
||||
bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color)
|
||||
x0 = (prev.x + point.x)/2
|
||||
y0 = (prev.y + point.y)/2
|
||||
// bmp.line(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, color2)
|
||||
// bmp.quadratic(x0, y0, (prev.x + point.x)/2, (prev.y + point.y)/2, prev.x, prev.y, color2)
|
||||
bmp.quadratic(x0, y0, (prev.x + point.x) / 2, (prev.y + point.y) / 2,
|
||||
prev.x, prev.y, color)
|
||||
x0 = (prev.x + point.x) / 2
|
||||
y0 = (prev.y + point.y) / 2
|
||||
}
|
||||
}
|
||||
|
||||
if count == glyph.contour_ends[c] {
|
||||
//dprintln("count == glyph.contour_ends[count]")
|
||||
// dprintln("count == glyph.contour_ends[count]")
|
||||
if s == 2 { // final point was off-curve. connect to start
|
||||
|
||||
mut start_point := glyph.points[contour_start]
|
||||
start_point.x, start_point.y = bmp.trf_ch(start_point)
|
||||
if point.on_curve {
|
||||
//ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||
//point.x + x, point.y + y);
|
||||
//bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000))
|
||||
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||
// point.x + x, point.y + y);
|
||||
// bmp.line(x0, y0, start_point.x + in_x, start_point.y + in_y, u32(0x00FF0000))
|
||||
|
||||
bmp.quadratic(x0, y0, start_point.x, start_point.y ,
|
||||
// start_point.x + in_x, start_point.y + in_y, u32(0xFF00FF00))
|
||||
start_point.x, start_point.y, color)
|
||||
bmp.quadratic(x0, y0, start_point.x, start_point.y, start_point.x,
|
||||
start_point.y, color)
|
||||
} else {
|
||||
//ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||
// ctx.quadraticCurveTo(prev.x + x, prev.y + y,
|
||||
// (prev.x + point.x) / 2 + x,
|
||||
// (prev.y + point.y) / 2 + y);
|
||||
|
||||
//bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000)
|
||||
bmp.quadratic(x0, y0, start_point.x, start_point.y,
|
||||
(point.x + start_point.x)/2,
|
||||
(point.y + start_point.y)/2,
|
||||
//u32(0xFF000000))
|
||||
color)
|
||||
// bmp.line(x0, y0, start_point.x, start_point.y, u32(0x00FF0000)
|
||||
// u32(0xFF000000))
|
||||
bmp.quadratic(x0, y0, start_point.x, start_point.y, (point.x +
|
||||
start_point.x) / 2, (point.y + start_point.y) / 2, color)
|
||||
}
|
||||
} else {
|
||||
// last point not in a curve
|
||||
//bmp.line(point.x, point.y, sp_x, sp_y, u32(0x00FF0000))
|
||||
// bmp.line(point.x, point.y, sp_x, sp_y, u32(0x00FF0000))
|
||||
bmp.line(point.x, point.y, sp_x, sp_y, color)
|
||||
}
|
||||
contour_start = count + 1
|
||||
|
@ -853,5 +820,5 @@ fn (mut bmp BitMap) draw_glyph(index u16) (int, int){
|
|||
x_max := glyph.x_max
|
||||
return x_min, x_max
|
||||
|
||||
//return glyph.x_min, glyph.x_max
|
||||
// return glyph.x_min, glyph.x_max
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module ttf
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* BMP render module utility functions
|
||||
|
@ -15,11 +16,9 @@ import math
|
|||
import gg
|
||||
import sokol.sgl
|
||||
|
||||
pub
|
||||
struct TTF_render_Sokol {
|
||||
pub struct TTF_render_Sokol {
|
||||
pub mut:
|
||||
bmp &BitMap // Base bitmap render
|
||||
|
||||
// rendering fields
|
||||
sg_img C.sg_image // sokol image
|
||||
scale_reduct f32 = 2.0 // scale of the cpu texture for filtering
|
||||
|
@ -31,25 +30,24 @@ pub mut:
|
|||
* Render functions
|
||||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf_skl TTF_render_Sokol) format_texture(){
|
||||
fn (mut tf_skl TTF_render_Sokol) format_texture() {
|
||||
tf_skl.bmp.format_texture()
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
||||
pub fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32) {
|
||||
scale_reduct := tf_skl.scale_reduct
|
||||
device_dpi := tf_skl.device_dpi
|
||||
font_size := in_font_size //* scale_reduct
|
||||
|
||||
// Formula: (font_size * device dpi) / (72dpi * em_unit)
|
||||
//scale := ((1.0 * devide_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
|
||||
// scale := ((1.0 * devide_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
|
||||
scale := f32(font_size * device_dpi) / f32(72 * tf_skl.bmp.tf.units_per_em)
|
||||
//dprintln("Scale: $scale")
|
||||
// dprintln("Scale: $scale")
|
||||
|
||||
tf_skl.bmp.scale = scale * scale_reduct
|
||||
w, h := tf_skl.bmp.get_bbox(in_txt)
|
||||
tf_skl.bmp.width = int(w)
|
||||
tf_skl.bmp.height = int((h+8))
|
||||
tf_skl.bmp.height = int((h + 8))
|
||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||
|
||||
// RAM buffer
|
||||
|
@ -57,7 +55,7 @@ fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
|||
if sz > 0 {
|
||||
free(tf_skl.bmp.buf)
|
||||
}
|
||||
dprintln("create_text Alloc: $sz bytes")
|
||||
dprintln('create_text Alloc: $sz bytes')
|
||||
tf_skl.bmp.buf = malloc(sz)
|
||||
tf_skl.bmp.buf_size = sz
|
||||
}
|
||||
|
@ -66,37 +64,36 @@ fn (mut tf_skl TTF_render_Sokol) create_text(in_txt string, in_font_size f32){
|
|||
|
||||
// draw the text
|
||||
mut y_base := int((tf_skl.bmp.tf.y_max - tf_skl.bmp.tf.y_min) * tf_skl.bmp.scale)
|
||||
tf_skl.bmp.set_pos(0,y_base)
|
||||
tf_skl.bmp.set_pos(0, y_base)
|
||||
tf_skl.bmp.clear()
|
||||
tf_skl.bmp.draw_text(in_txt)
|
||||
tf_skl.format_texture()
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32){
|
||||
pub fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h int, in_font_size f32) {
|
||||
scale_reduct := tf_skl.scale_reduct
|
||||
device_dpi := tf_skl.device_dpi
|
||||
font_size := in_font_size //* scale_reduct
|
||||
// Formula: (font_size * device dpi) / (72dpi * em_unit)
|
||||
//scale := ((1.0 * devide_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
|
||||
// scale := ((1.0 * devide_dpi )/ f32(72 * tf_skl.bmp.tf.units_per_em))* font_size
|
||||
scale := f32(font_size * device_dpi) / f32(72 * tf_skl.bmp.tf.units_per_em)
|
||||
//dprintln("Scale: $scale")
|
||||
// dprintln("Scale: $scale")
|
||||
|
||||
tf_skl.bmp.scale = scale * scale_reduct
|
||||
w := in_w
|
||||
h := in_h
|
||||
tf_skl.bmp.width = int(w * scale_reduct + 0.5)
|
||||
tf_skl.bmp.height = int((h+2) * scale_reduct + 0.5)
|
||||
tf_skl.bmp.height = int((h + 2) * scale_reduct + 0.5)
|
||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||
|
||||
//if true { return }
|
||||
// if true { return }
|
||||
|
||||
// RAM buffer
|
||||
if sz > tf_skl.bmp.buf_size {
|
||||
if sz > 0 {
|
||||
free(tf_skl.bmp.buf)
|
||||
}
|
||||
dprintln("Alloc: $sz bytes")
|
||||
dprintln('Alloc: $sz bytes')
|
||||
tf_skl.bmp.buf = malloc(sz)
|
||||
tf_skl.bmp.buf_size = sz
|
||||
}
|
||||
|
@ -105,19 +102,19 @@ fn (mut tf_skl TTF_render_Sokol) create_text_block(in_txt string, in_w int, in_h
|
|||
|
||||
// draw the text
|
||||
mut y_base := int((tf_skl.bmp.tf.y_max - tf_skl.bmp.tf.y_min) * tf_skl.bmp.scale)
|
||||
tf_skl.bmp.set_pos(0,y_base)
|
||||
tf_skl.bmp.set_pos(0, y_base)
|
||||
tf_skl.bmp.clear()
|
||||
|
||||
tf_skl.bmp.draw_text_block(in_txt, {x: 0, y:0, w:w, h:h})
|
||||
tf_skl.bmp.draw_text_block(in_txt, x: 0, y: 0, w: w, h: h)
|
||||
tf_skl.format_texture()
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Sokol Render functions
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (mut tf_skl TTF_render_Sokol) create_texture(){
|
||||
pub fn (mut tf_skl TTF_render_Sokol) create_texture() {
|
||||
w := tf_skl.bmp.width
|
||||
h := tf_skl.bmp.height
|
||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||
|
@ -127,7 +124,7 @@ fn (mut tf_skl TTF_render_Sokol) create_texture(){
|
|||
num_mipmaps: 0
|
||||
min_filter: .linear
|
||||
mag_filter: .linear
|
||||
//usage: .dynamic
|
||||
// usage: .dynamic
|
||||
wrap_u: .clamp_to_edge
|
||||
wrap_v: .clamp_to_edge
|
||||
label: &byte(0)
|
||||
|
@ -140,31 +137,28 @@ fn (mut tf_skl TTF_render_Sokol) create_texture(){
|
|||
}
|
||||
|
||||
simg := C.sg_make_image(&img_desc)
|
||||
//free(tf_skl.bmp.buf) // DONT FREE IF Dynamic
|
||||
// free(tf_skl.bmp.buf) // DONT FREE IF Dynamic
|
||||
tf_skl.sg_img = simg
|
||||
}
|
||||
|
||||
pub
|
||||
fn (tf_skl TTF_render_Sokol) destroy_texture(){
|
||||
pub fn (tf_skl TTF_render_Sokol) destroy_texture() {
|
||||
C.sg_destroy_image(tf_skl.sg_img)
|
||||
}
|
||||
|
||||
// Use only if usage: .dynamic
|
||||
pub
|
||||
fn (mut tf_skl TTF_render_Sokol) update_text_texture(){
|
||||
pub fn (mut tf_skl TTF_render_Sokol) update_text_texture() {
|
||||
sz := tf_skl.bmp.width * tf_skl.bmp.height * tf_skl.bmp.bp
|
||||
mut tmp_sbc := C.sg_image_content{}
|
||||
tmp_sbc.subimage[0][0] = C.sg_subimage_content {
|
||||
tmp_sbc.subimage[0][0] = C.sg_subimage_content{
|
||||
ptr: tf_skl.bmp.buf
|
||||
size: sz
|
||||
}
|
||||
C.sg_update_image(tf_skl.sg_img, &tmp_sbc)
|
||||
}
|
||||
|
||||
pub
|
||||
fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
||||
//width := tf_skl.bmp.width >> 1
|
||||
//height := tf_skl.bmp.height >> 1
|
||||
pub fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
||||
// width := tf_skl.bmp.width >> 1
|
||||
// height := tf_skl.bmp.height >> 1
|
||||
sgl.push_matrix()
|
||||
|
||||
width := tf_skl.bmp.width / (tf_skl.scale_reduct)
|
||||
|
@ -182,10 +176,22 @@ fn (tf_skl TTF_render_Sokol) draw_text_bmp(ctx &gg.Context, x f32, y f32) {
|
|||
ca := f32(math.cos(tf_skl.bmp.angle))
|
||||
sa := f32(math.sin(tf_skl.bmp.angle))
|
||||
m := [
|
||||
f32(ca),-sa,0,0,
|
||||
sa,ca,0,0,
|
||||
0,0,1,0,
|
||||
x,y,0,1
|
||||
f32(ca),
|
||||
-sa,
|
||||
0,
|
||||
0,
|
||||
sa,
|
||||
ca,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
x,
|
||||
y,
|
||||
0,
|
||||
1,
|
||||
]
|
||||
sgl.mult_matrix(m)
|
||||
//
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
module ttf
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* BMP render module utility functions
|
||||
|
@ -11,8 +12,7 @@ module ttf
|
|||
*
|
||||
* TODO:
|
||||
**********************************************************************/
|
||||
pub
|
||||
struct Text_block {
|
||||
pub struct Text_block {
|
||||
x int // x postion of the left high corner
|
||||
y int // y postion of the left high corner
|
||||
w int // width of the text block
|
||||
|
@ -21,26 +21,25 @@ struct Text_block {
|
|||
}
|
||||
|
||||
fn (mut dev BitMap) get_justify_space_cw(txt string, w int, block_w int, space_cw int) f32 {
|
||||
num_spaces := txt.count(" ")
|
||||
num_spaces := txt.count(' ')
|
||||
if num_spaces < 1 {
|
||||
return 0
|
||||
}
|
||||
delta := block_w - w
|
||||
//println("num spc: $num_spaces")
|
||||
//println("delta: ${txt} w:$w bw:$block_w space_cw:$space_cw")
|
||||
res := f32(delta)/f32(num_spaces)/f32(space_cw)
|
||||
//println("res: $res")
|
||||
// println("num spc: $num_spaces")
|
||||
// println("delta: ${txt} w:$w bw:$block_w space_cw:$space_cw")
|
||||
res := f32(delta) / f32(num_spaces) / f32(space_cw)
|
||||
// println("res: $res")
|
||||
return res
|
||||
}
|
||||
|
||||
// write out a text
|
||||
pub
|
||||
fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
||||
pub fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
||||
mut x := block.x
|
||||
mut y := block.y
|
||||
mut y_base := int((bmp.tf.y_max - bmp.tf.y_min) * bmp.scale)
|
||||
|
||||
//bmp.box(x, y, x + block.w, y + block.h, u32(0xFF00_0000))
|
||||
// bmp.box(x, y, x + block.w, y + block.h, u32(0xFF00_0000))
|
||||
|
||||
// spaces data
|
||||
mut space_cw, _ := bmp.tf.get_horizontal_metrics(u16(` `))
|
||||
|
@ -57,40 +56,40 @@ fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
|||
|
||||
for txt in text.split_into_lines() {
|
||||
bmp.space_cw = old_space_cw
|
||||
mut w,mut h := bmp.get_bbox(txt)
|
||||
mut w, mut h := bmp.get_bbox(txt)
|
||||
if w <= block.w || block.cut_lines == false {
|
||||
//println("Solid block!")
|
||||
// println("Solid block!")
|
||||
left_offset := int((block.w - w) * offset_flag)
|
||||
if bmp.justify && (f32(w) / f32(block.w)) >= bmp.justify_fill_ratio {
|
||||
bmp.space_cw = old_space_cw + bmp.get_justify_space_cw(txt, w, block.w, space_cw)
|
||||
}
|
||||
bmp.set_pos(x + left_offset ,y + y_base)
|
||||
bmp.set_pos(x + left_offset, y + y_base)
|
||||
bmp.draw_text(txt)
|
||||
//---- DEBUG ----
|
||||
//mut txt_w , mut txt_h := bmp.draw_text(txt)
|
||||
//bmp.box(x + left_offset,y+y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) )
|
||||
// mut txt_w , mut txt_h := bmp.draw_text(txt)
|
||||
// bmp.box(x + left_offset,y+y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) )
|
||||
//---------------
|
||||
y += y_base
|
||||
} else {
|
||||
//println("to cut: ${txt}")
|
||||
mut txt1 := txt.split(" ")
|
||||
mut c:= txt1.len
|
||||
//mut done := false
|
||||
// println("to cut: ${txt}")
|
||||
mut txt1 := txt.split(' ')
|
||||
mut c := txt1.len
|
||||
// mut done := false
|
||||
for c > 0 {
|
||||
tmp_str := txt1[0..c].join(' ')
|
||||
//println("tmp_str: ${tmp_str}")
|
||||
// println("tmp_str: ${tmp_str}")
|
||||
if tmp_str.len < 1 {
|
||||
break
|
||||
}
|
||||
|
||||
bmp.space_cw = old_space_cw
|
||||
w,h = bmp.get_bbox(tmp_str)
|
||||
w, h = bmp.get_bbox(tmp_str)
|
||||
if w <= block.w {
|
||||
mut left_offset := int((block.w - w) * offset_flag)
|
||||
if bmp.justify && (f32(w) / f32(block.w)) >= bmp.justify_fill_ratio {
|
||||
//println("cut phase!")
|
||||
// println("cut phase!")
|
||||
bmp.space_cw = 0.0
|
||||
w,h = bmp.get_bbox(tmp_str)
|
||||
w, h = bmp.get_bbox(tmp_str)
|
||||
left_offset = int((block.w - w) * offset_flag)
|
||||
bmp.space_cw = bmp.get_justify_space_cw(tmp_str, w, block.w, space_cw)
|
||||
} else {
|
||||
|
@ -99,16 +98,16 @@ fn (mut bmp BitMap) draw_text_block(text string, block Text_block) {
|
|||
bmp.set_pos(x + left_offset, y + y_base)
|
||||
bmp.draw_text(tmp_str)
|
||||
//---- DEBUG ----
|
||||
//txt_w , txt_h := bmp.draw_text(tmp_str)
|
||||
//println("printing [${x},${y}] => '${tmp_str}' space_cw: $bmp.space_cw")
|
||||
//bmp.box(x + left_offset,y + y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) )
|
||||
// txt_w , txt_h := bmp.draw_text(tmp_str)
|
||||
// println("printing [${x},${y}] => '${tmp_str}' space_cw: $bmp.space_cw")
|
||||
// bmp.box(x + left_offset,y + y_base - int((bmp.tf.y_min)*bmp.scale), x + txt_w + left_offset, y + y_base - int((bmp.tf.y_max) * bmp.scale), u32(0x00ff_0000) )
|
||||
//---------------
|
||||
y += y_base
|
||||
txt1 = txt1[c..]
|
||||
c= txt1.len
|
||||
c = txt1.len
|
||||
//---- DEBUG ----
|
||||
//txt2 := txt1.join(' ')
|
||||
//println("new string: ${txt2} len: ${c}")
|
||||
// txt2 := txt1.join(' ')
|
||||
// println("new string: ${txt2} len: ${c}")
|
||||
//---------------
|
||||
} else {
|
||||
c--
|
||||
|
|
422
vlib/x/ttf/ttf.v
422
vlib/x/ttf/ttf.v
|
@ -1,4 +1,5 @@
|
|||
module ttf
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* TrueTypeFont reader V implementation
|
||||
|
@ -16,7 +17,6 @@ module ttf
|
|||
**********************************************************************/
|
||||
import strings
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* CMAP structs
|
||||
|
@ -33,7 +33,7 @@ mut:
|
|||
struct TrueTypeCmap {
|
||||
mut:
|
||||
format int
|
||||
cache []int = []int{ len: 65536, init: -1 } // for now we allocate 2^16 charcode
|
||||
cache []int = []int{len: 65536, init: -1} // for now we allocate 2^16 charcode
|
||||
segments []Segment
|
||||
arr []int
|
||||
}
|
||||
|
@ -43,21 +43,16 @@ mut:
|
|||
* TTF_File structs
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
struct TTF_File{
|
||||
pub struct TTF_File {
|
||||
pub mut:
|
||||
buf []byte
|
||||
pos u32
|
||||
|
||||
length u16
|
||||
|
||||
scalar_type u32
|
||||
search_range u16
|
||||
entry_selector u16
|
||||
range_shift u16
|
||||
|
||||
tables map[string]Offset_Table
|
||||
|
||||
version f32
|
||||
font_revision f32
|
||||
checksum_adjustment u32
|
||||
|
@ -75,14 +70,11 @@ pub mut:
|
|||
font_direction_hint i16
|
||||
index_to_loc_format i16
|
||||
glyph_data_format i16
|
||||
|
||||
font_family string
|
||||
font_sub_family string
|
||||
full_name string
|
||||
postscript_name string
|
||||
|
||||
cmaps []TrueTypeCmap
|
||||
|
||||
ascent i16
|
||||
descent i16
|
||||
line_gap i16
|
||||
|
@ -95,34 +87,30 @@ pub mut:
|
|||
caret_offset i16
|
||||
metric_data_format i16
|
||||
num_of_long_hor_metrics u16
|
||||
|
||||
kern []Kern0Table
|
||||
|
||||
// cache
|
||||
glyph_cache map[int]Glyph
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut tf TTF_File) init() {
|
||||
pub fn (mut tf TTF_File) init() {
|
||||
tf.read_offset_tables()
|
||||
tf.read_head_table()
|
||||
//dprintln(tf.get_info_string())
|
||||
// dprintln(tf.get_info_string())
|
||||
tf.read_name_table()
|
||||
tf.read_cmap_table()
|
||||
tf.read_hhea_table()
|
||||
tf.read_kern_table()
|
||||
tf.length = tf.glyph_count()
|
||||
dprintln("Number of symbols: $tf.length")
|
||||
dprintln("*****************************")
|
||||
dprintln('Number of symbols: $tf.length')
|
||||
dprintln('*****************************')
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* TTF_File Glyph Structs
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
pub
|
||||
struct Point {
|
||||
pub struct Point {
|
||||
pub mut:
|
||||
x int
|
||||
y int
|
||||
|
@ -135,15 +123,14 @@ mut:
|
|||
}
|
||||
|
||||
// type of glyph
|
||||
const(
|
||||
const (
|
||||
g_type_simple = u16(1) // simple type
|
||||
g_type_complex = u16(2) // compound type
|
||||
)
|
||||
|
||||
pub
|
||||
struct Glyph {
|
||||
pub struct Glyph {
|
||||
pub mut:
|
||||
g_type u16 = g_type_simple
|
||||
g_type u16 = ttf.g_type_simple
|
||||
contour_ends []u16
|
||||
number_of_contours i16
|
||||
points []Point
|
||||
|
@ -155,17 +142,15 @@ pub mut:
|
|||
components []Component
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* TTF_File metrics and glyph
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
||||
assert"hmtx" in tf.tables
|
||||
pub fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
||||
assert 'hmtx' in tf.tables
|
||||
old_pos := tf.pos
|
||||
mut offset := tf.tables["hmtx"].offset
|
||||
mut offset := tf.tables['hmtx'].offset
|
||||
|
||||
mut advance_width := 0
|
||||
mut left_side_bearing := 0
|
||||
|
@ -174,25 +159,26 @@ fn (mut tf TTF_File) get_horizontal_metrics(glyph_index u16) (int, int) {
|
|||
tf.pos = offset
|
||||
advance_width = tf.get_u16()
|
||||
left_side_bearing = tf.get_i16()
|
||||
//dprintln("Found h_metric aw: $advance_width lsb: $left_side_bearing")
|
||||
// dprintln("Found h_metric aw: $advance_width lsb: $left_side_bearing")
|
||||
} else {
|
||||
// read the last entry of the hMetrics array
|
||||
tf.pos = offset + (tf.num_of_long_hor_metrics - 1) * 4
|
||||
advance_width = tf.get_u16()
|
||||
tf.pos = offset + tf.num_of_long_hor_metrics * 4 + 2 * (glyph_index - tf.num_of_long_hor_metrics)
|
||||
tf.pos = offset + tf.num_of_long_hor_metrics * 4 +
|
||||
2 * (glyph_index - tf.num_of_long_hor_metrics)
|
||||
left_side_bearing = tf.get_fword()
|
||||
}
|
||||
tf.pos = old_pos
|
||||
return advance_width, left_side_bearing
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) get_glyph_offset(index u32) u32{
|
||||
fn (mut tf TTF_File) get_glyph_offset(index u32) u32 {
|
||||
// check if needed tables exists
|
||||
assert "loca" in tf.tables
|
||||
assert "glyf" in tf.tables
|
||||
assert 'loca' in tf.tables
|
||||
assert 'glyf' in tf.tables
|
||||
mut old_pos := tf.pos
|
||||
|
||||
table := tf.tables["loca"]
|
||||
table := tf.tables['loca']
|
||||
mut offset := u32(0)
|
||||
mut next := u32(0)
|
||||
if tf.index_to_loc_format == 1 {
|
||||
|
@ -209,37 +195,36 @@ fn (mut tf TTF_File) get_glyph_offset(index u32) u32{
|
|||
// indicates glyph has no outline( eg space)
|
||||
return 0
|
||||
}
|
||||
|
||||
//dprintln("Offset for glyph index $index is $offset")
|
||||
// dprintln("Offset for glyph index $index is $offset")
|
||||
tf.pos = old_pos
|
||||
return offset + tf.tables['glyf'].offset
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) glyph_count() u16{
|
||||
assert "maxp" in tf.tables
|
||||
fn (mut tf TTF_File) glyph_count() u16 {
|
||||
assert 'maxp' in tf.tables
|
||||
old_pos := tf.pos
|
||||
tf.pos = tf.tables["maxp"].offset + 4
|
||||
tf.pos = tf.tables['maxp'].offset + 4
|
||||
count := tf.get_u16()
|
||||
tf.pos = old_pos
|
||||
return count
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
||||
pub fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
||||
offset := tf.get_glyph_offset(index)
|
||||
//dprintln("offset: $offset")
|
||||
if offset == 0 || offset >= tf.tables["glyf"].offset + tf.tables["glyf"].length {
|
||||
dprintln("No glyph found!")
|
||||
// dprintln("offset: $offset")
|
||||
if offset == 0 || offset >= tf.tables['glyf'].offset + tf.tables['glyf'].length {
|
||||
dprintln('No glyph found!')
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
assert offset >= tf.tables["glyf"].offset
|
||||
assert offset < tf.tables["glyf"].offset + tf.tables["glyf"].length
|
||||
assert offset >= tf.tables['glyf'].offset
|
||||
assert offset < tf.tables['glyf'].offset + tf.tables['glyf'].length
|
||||
|
||||
tf.pos = offset
|
||||
//dprintln("file seek read_glyph: $tf.pos")
|
||||
// dprintln("file seek read_glyph: $tf.pos")
|
||||
|
||||
/*number_of_contours*/ _ := tf.get_i16()
|
||||
// number_of_contours
|
||||
_ := tf.get_i16()
|
||||
x_min := tf.get_fword()
|
||||
y_min := tf.get_fword()
|
||||
x_max := tf.get_fword()
|
||||
|
@ -248,29 +233,29 @@ fn (mut tf TTF_File) read_glyph_dim(index u16) (int, int, int, int) {
|
|||
return x_min, x_max, y_min, y_max
|
||||
}
|
||||
|
||||
pub
|
||||
fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
||||
index_int := int(index) //index.str()
|
||||
if index_int in tf.glyph_cache{
|
||||
//dprintln("Found glyp: ${index}")
|
||||
pub fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
||||
index_int := int(index) // index.str()
|
||||
if index_int in tf.glyph_cache {
|
||||
// dprintln("Found glyp: ${index}")
|
||||
return tf.glyph_cache[index_int]
|
||||
}
|
||||
//dprintln("Create glyp: ${index}")
|
||||
// dprintln("Create glyp: ${index}")
|
||||
|
||||
offset := tf.get_glyph_offset(index)
|
||||
//dprintln("offset: $offset")
|
||||
if offset == 0 || offset >= tf.tables["glyf"].offset + tf.tables["glyf"].length {
|
||||
dprintln("No glyph found!")
|
||||
// dprintln("offset: $offset")
|
||||
if offset == 0 || offset >= tf.tables['glyf'].offset + tf.tables['glyf'].length {
|
||||
dprintln('No glyph found!')
|
||||
return Glyph{}
|
||||
}
|
||||
|
||||
assert offset >= tf.tables["glyf"].offset
|
||||
assert offset < tf.tables["glyf"].offset + tf.tables["glyf"].length
|
||||
assert offset >= tf.tables['glyf'].offset
|
||||
assert offset < tf.tables['glyf'].offset + tf.tables['glyf'].length
|
||||
|
||||
tf.pos = offset
|
||||
//dprintln("file seek read_glyph: $tf.pos")
|
||||
// dprintln("file seek read_glyph: $tf.pos")
|
||||
|
||||
/* ---- BUG TO SOLVE -----
|
||||
/*
|
||||
---- BUG TO SOLVE -----
|
||||
--- Order of the data if printed in the main is shuffled!! Very Strange
|
||||
mut tmp_glyph := Glyph{
|
||||
number_of_contours : tf.get_i16()
|
||||
|
@ -288,15 +273,15 @@ fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
|||
tmp_glyph.x_max = tf.get_fword()
|
||||
tmp_glyph.y_max = tf.get_fword()
|
||||
|
||||
//dprintln("file seek after read_glyph: $tf.pos")
|
||||
// dprintln("file seek after read_glyph: $tf.pos")
|
||||
|
||||
assert tmp_glyph.number_of_contours >= -1
|
||||
|
||||
if tmp_glyph.number_of_contours == -1 {
|
||||
//dprintln("read_compound_glyph")
|
||||
// dprintln("read_compound_glyph")
|
||||
tf.read_compound_glyph(mut tmp_glyph)
|
||||
} else {
|
||||
//dprintln("read_simple_glyph")
|
||||
// dprintln("read_simple_glyph")
|
||||
tf.read_simple_glyph(mut tmp_glyph)
|
||||
}
|
||||
|
||||
|
@ -304,7 +289,7 @@ fn (mut tf TTF_File) read_glyph(index u16) Glyph {
|
|||
return tmp_glyph
|
||||
}
|
||||
|
||||
const(
|
||||
const (
|
||||
tfk_on_curve = 1
|
||||
tfk_x_is_byte = 2
|
||||
tfk_y_is_byte = 4
|
||||
|
@ -313,12 +298,12 @@ const(
|
|||
tfk_y_delta = 32
|
||||
)
|
||||
|
||||
fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
||||
fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph) {
|
||||
if in_glyph.number_of_contours == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _ in 0..in_glyph.number_of_contours {
|
||||
for _ in 0 .. in_glyph.number_of_contours {
|
||||
in_glyph.contour_ends << tf.get_u16()
|
||||
}
|
||||
|
||||
|
@ -341,10 +326,9 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
|||
in_glyph.points << Point{
|
||||
x: 0
|
||||
y: 0
|
||||
on_curve: (flag & tfk_on_curve) > 0
|
||||
on_curve: (flag & ttf.tfk_on_curve) > 0
|
||||
}
|
||||
|
||||
if (flag & tfk_repeat) > 0 {
|
||||
if (flag & ttf.tfk_repeat) > 0 {
|
||||
mut repeat_count := tf.get_u8()
|
||||
assert repeat_count > 0
|
||||
i += repeat_count
|
||||
|
@ -353,7 +337,7 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
|||
in_glyph.points << Point{
|
||||
x: 0
|
||||
y: 0
|
||||
on_curve: (flag & tfk_on_curve) > 0
|
||||
on_curve: (flag & ttf.tfk_on_curve) > 0
|
||||
}
|
||||
repeat_count--
|
||||
}
|
||||
|
@ -363,39 +347,39 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
|||
|
||||
// read coords x
|
||||
mut value := 0
|
||||
for i_x in 0..num_points {
|
||||
for i_x in 0 .. num_points {
|
||||
flag_x := flags[i_x]
|
||||
if (flag_x & tfk_x_is_byte) > 0 {
|
||||
if (flag_x & tfk_x_delta) > 0 {
|
||||
if (flag_x & ttf.tfk_x_is_byte) > 0 {
|
||||
if (flag_x & ttf.tfk_x_delta) > 0 {
|
||||
value += tf.get_u8()
|
||||
} else {
|
||||
value -= tf.get_u8()
|
||||
}
|
||||
} else if (~flag_x & tfk_x_delta) > 0 {
|
||||
} else if (~flag_x & ttf.tfk_x_delta) > 0 {
|
||||
value += tf.get_i16()
|
||||
} else {
|
||||
// value is unchanged
|
||||
}
|
||||
//dprintln("$i_x x: $value")
|
||||
// dprintln("$i_x x: $value")
|
||||
in_glyph.points[i_x].x = value
|
||||
}
|
||||
|
||||
// read coords y
|
||||
value = 0
|
||||
for i_y in 0..num_points {
|
||||
for i_y in 0 .. num_points {
|
||||
flag_y := flags[i_y]
|
||||
if (flag_y & tfk_y_is_byte) > 0 {
|
||||
if (flag_y & tfk_y_delta) > 0 {
|
||||
if (flag_y & ttf.tfk_y_is_byte) > 0 {
|
||||
if (flag_y & ttf.tfk_y_delta) > 0 {
|
||||
value += tf.get_u8()
|
||||
} else {
|
||||
value -= tf.get_u8()
|
||||
}
|
||||
} else if (~flag_y & tfk_y_delta) > 0 {
|
||||
} else if (~flag_y & ttf.tfk_y_delta) > 0 {
|
||||
value += tf.get_i16()
|
||||
} else {
|
||||
// value is unchanged
|
||||
}
|
||||
//dprintln("$i_y y: $value")
|
||||
// dprintln("$i_y y: $value")
|
||||
in_glyph.points[i_y].y = value
|
||||
}
|
||||
|
||||
|
@ -403,7 +387,7 @@ fn (mut tf TTF_File) read_simple_glyph(mut in_glyph Glyph){
|
|||
in_glyph.valid_glyph = true
|
||||
}
|
||||
|
||||
const(
|
||||
const (
|
||||
tfkc_arg_1_and_2_are_words = 1
|
||||
tfkc_args_are_xy_values = 2
|
||||
tfkc_round_xy_to_grid = 4
|
||||
|
@ -425,11 +409,11 @@ mut:
|
|||
matrix []f32 = [f32(1.0), 0, 0, 1.0, 0, 0]
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
||||
in_glyph.g_type = g_type_complex
|
||||
fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph) {
|
||||
in_glyph.g_type = ttf.g_type_complex
|
||||
mut component := Component{}
|
||||
mut flags := tfkc_more_components
|
||||
for (flags & tfkc_more_components) > 0 {
|
||||
mut flags := ttf.tfkc_more_components
|
||||
for (flags & ttf.tfkc_more_components) > 0 {
|
||||
mut arg1 := i16(0)
|
||||
mut arg2 := i16(0)
|
||||
|
||||
|
@ -437,7 +421,7 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
|||
|
||||
component.glyph_index = tf.get_u16()
|
||||
|
||||
if (flags & tfkc_arg_1_and_2_are_words) > 0 {
|
||||
if (flags & ttf.tfkc_arg_1_and_2_are_words) > 0 {
|
||||
arg1 = tf.get_i16()
|
||||
arg2 = tf.get_i16()
|
||||
} else {
|
||||
|
@ -445,7 +429,7 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
|||
arg2 = tf.get_u8()
|
||||
}
|
||||
|
||||
if (flags & tfkc_args_are_xy_values) > 0 {
|
||||
if (flags & ttf.tfkc_args_are_xy_values) > 0 {
|
||||
component.matrix[4] = arg1
|
||||
component.matrix[5] = arg2
|
||||
} else {
|
||||
|
@ -453,28 +437,27 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
|||
component.src_point_index = arg2
|
||||
}
|
||||
|
||||
if (flags & tfkc_we_have_a_scale) > 0 {
|
||||
if (flags & ttf.tfkc_we_have_a_scale) > 0 {
|
||||
component.matrix[0] = tf.get_2dot14()
|
||||
component.matrix[3] = component.matrix[0]
|
||||
} else if (flags & tfkc_we_have_an_x_and_y_scale) > 0 {
|
||||
} else if (flags & ttf.tfkc_we_have_an_x_and_y_scale) > 0 {
|
||||
component.matrix[0] = tf.get_2dot14()
|
||||
component.matrix[3] = tf.get_2dot14()
|
||||
} else if (flags & tfkc_we_have_a_two_by_two) > 0 {
|
||||
} else if (flags & ttf.tfkc_we_have_a_two_by_two) > 0 {
|
||||
component.matrix[0] = tf.get_2dot14()
|
||||
component.matrix[1] = tf.get_2dot14()
|
||||
component.matrix[2] = tf.get_2dot14()
|
||||
component.matrix[3] = tf.get_2dot14()
|
||||
}
|
||||
|
||||
//dprintln("Read component glyph index ${component.glyph_index}")
|
||||
//dprintln("Transform: ${component.matrix}")
|
||||
// dprintln("Read component glyph index ${component.glyph_index}")
|
||||
// dprintln("Transform: ${component.matrix}")
|
||||
|
||||
old_pos := tf.pos
|
||||
|
||||
simple_glyph := tf.read_glyph(component.glyph_index)
|
||||
if simple_glyph.valid_glyph {
|
||||
point_offset := in_glyph.points.len
|
||||
for i in 0..simple_glyph.contour_ends.len {
|
||||
for i in 0 .. simple_glyph.contour_ends.len {
|
||||
in_glyph.contour_ends << u16(simple_glyph.contour_ends[i] + point_offset)
|
||||
}
|
||||
|
||||
|
@ -495,10 +478,9 @@ fn (mut tf TTF_File) read_compound_glyph(mut in_glyph Glyph){
|
|||
|
||||
in_glyph.number_of_contours = i16(in_glyph.contour_ends.len)
|
||||
|
||||
if (flags & tfkc_we_have_instructions) > 0 {
|
||||
if (flags & ttf.tfkc_we_have_instructions) > 0 {
|
||||
tf.pos = tf.get_u16() + tf.pos
|
||||
}
|
||||
|
||||
// ok we have a valid glyph
|
||||
in_glyph.valid_glyph = true
|
||||
}
|
||||
|
@ -537,10 +519,8 @@ fn (mut tf TTF_File) get_fword() i16 {
|
|||
}
|
||||
|
||||
fn (mut tf TTF_File) get_u32() u32 {
|
||||
x :=(u32(tf.buf[tf.pos]) << u32(24)) |
|
||||
(u32(tf.buf[tf.pos + 1]) << u32(16)) |
|
||||
(u32(tf.buf[tf.pos + 2]) << u32(8)) |
|
||||
u32(tf.buf[tf.pos + 3])
|
||||
x := (u32(tf.buf[tf.pos]) << u32(24)) | (u32(tf.buf[tf.pos +
|
||||
1]) << u32(16)) | (u32(tf.buf[tf.pos + 2]) << u32(8)) | u32(tf.buf[tf.pos + 3])
|
||||
tf.pos += 4
|
||||
return x
|
||||
}
|
||||
|
@ -560,16 +540,16 @@ fn (mut tf TTF_File) get_fixed() f32 {
|
|||
fn (mut tf TTF_File) get_string(length int) string {
|
||||
tmp_pos := u64(tf.pos)
|
||||
tf.pos += u32(length)
|
||||
return unsafe{ tos(byteptr(u64(tf.buf.data)+tmp_pos), length) }
|
||||
return unsafe { tos(byteptr(u64(tf.buf.data) + tmp_pos), length) }
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) get_unicode_string(length int) string {
|
||||
mut tmp_txt := strings.new_builder(length)
|
||||
mut real_len := 0
|
||||
|
||||
for _ in 0..(length>>1) {
|
||||
for _ in 0 .. (length >> 1) {
|
||||
c := tf.get_u16()
|
||||
c_len := ((0xe5000000>>((c>>3) & 0x1e)) & 3) + 1
|
||||
c_len := ((0xe5000000 >> ((c >> 3) & 0x1e)) & 3) + 1
|
||||
real_len += c_len
|
||||
if c_len == 1 {
|
||||
tmp_txt.write_b(byte(c & 0xff))
|
||||
|
@ -577,11 +557,11 @@ fn (mut tf TTF_File) get_unicode_string(length int) string {
|
|||
tmp_txt.write_b(byte((c >> 8) & 0xff))
|
||||
tmp_txt.write_b(byte(c & 0xff))
|
||||
}
|
||||
//dprintln("c: ${c:c}|${ byte(c &0xff) :c} c_len: ${c_len} str_len: ${real_len} in_len: ${length}")
|
||||
// dprintln("c: ${c:c}|${ byte(c &0xff) :c} c_len: ${c_len} str_len: ${real_len} in_len: ${length}")
|
||||
}
|
||||
tf.pos += u32(real_len)
|
||||
res_txt := tmp_txt.str()
|
||||
//dprintln("get_unicode_string: ${res_txt}")
|
||||
// dprintln("get_unicode_string: ${res_txt}")
|
||||
return res_txt
|
||||
}
|
||||
|
||||
|
@ -597,7 +577,7 @@ fn (mut tf TTF_File) calc_checksum(offset u32, length u32) u32 {
|
|||
mut sum := u64(0)
|
||||
mut nlongs := int((length + 3) >> 2)
|
||||
tf.pos = offset
|
||||
//dprintln("offs: $offset nlongs: $nlongs")
|
||||
// dprintln("offs: $offset nlongs: $nlongs")
|
||||
for nlongs > 0 {
|
||||
sum = sum + u64(tf.get_u32())
|
||||
nlongs--
|
||||
|
@ -619,21 +599,21 @@ mut:
|
|||
}
|
||||
|
||||
fn (mut tf TTF_File) read_offset_tables() {
|
||||
dprintln("*** READ TABLES OFFSET ***")
|
||||
dprintln('*** READ TABLES OFFSET ***')
|
||||
tf.pos = 0
|
||||
tf.scalar_type = tf.get_u32()
|
||||
num_tables := tf.get_u16()
|
||||
tf.search_range = tf.get_u16()
|
||||
tf.entry_selector= tf.get_u16()
|
||||
tf.entry_selector = tf.get_u16()
|
||||
tf.range_shift = tf.get_u16()
|
||||
|
||||
dprintln("scalar_type : [0x$tf.scalar_type.hex()]")
|
||||
dprintln("num tables : [$num_tables]")
|
||||
dprintln("search_range : [0x$tf.search_range.hex()]")
|
||||
dprintln("entry_selector: [0x$tf.entry_selector.hex()]")
|
||||
dprintln("range_shift : [0x$tf.range_shift.hex()]")
|
||||
dprintln('scalar_type : [0x$tf.scalar_type.hex()]')
|
||||
dprintln('num tables : [$num_tables]')
|
||||
dprintln('search_range : [0x$tf.search_range.hex()]')
|
||||
dprintln('entry_selector: [0x$tf.entry_selector.hex()]')
|
||||
dprintln('range_shift : [0x$tf.range_shift.hex()]')
|
||||
|
||||
mut i:= 0
|
||||
mut i := 0
|
||||
for i < num_tables {
|
||||
tag := tf.get_string(4)
|
||||
tf.tables[tag] = {
|
||||
|
@ -641,15 +621,15 @@ fn (mut tf TTF_File) read_offset_tables() {
|
|||
offset: tf.get_u32()
|
||||
length: tf.get_u32()
|
||||
}
|
||||
dprintln("Table: [$tag]")
|
||||
//dprintln("${tf.tables[tag]}")
|
||||
dprintln('Table: [$tag]')
|
||||
// dprintln("${tf.tables[tag]}")
|
||||
|
||||
if tag != 'head' {
|
||||
assert tf.calc_checksum(tf.tables[tag].offset, tf.tables[tag].length) == tf.tables[tag].checksum
|
||||
}
|
||||
i++
|
||||
}
|
||||
dprintln("*** END READ TABLES OFFSET ***")
|
||||
dprintln('*** END READ TABLES OFFSET ***')
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -658,9 +638,9 @@ fn (mut tf TTF_File) read_offset_tables() {
|
|||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) read_head_table() {
|
||||
dprintln("*** READ HEAD TABLE ***")
|
||||
tf.pos = tf.tables["head"].offset
|
||||
dprintln("Offset: $tf.pos")
|
||||
dprintln('*** READ HEAD TABLE ***')
|
||||
tf.pos = tf.tables['head'].offset
|
||||
dprintln('Offset: $tf.pos')
|
||||
|
||||
tf.version = tf.get_fixed()
|
||||
tf.font_revision = tf.get_fixed()
|
||||
|
@ -688,20 +668,22 @@ fn (mut tf TTF_File) read_head_table() {
|
|||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) read_name_table() {
|
||||
dprintln("*** READ NAME TABLE ***")
|
||||
assert "name" in tf.tables
|
||||
table_offset := tf.tables["name"].offset
|
||||
tf.pos = tf.tables["name"].offset
|
||||
dprintln('*** READ NAME TABLE ***')
|
||||
assert 'name' in tf.tables
|
||||
table_offset := tf.tables['name'].offset
|
||||
tf.pos = tf.tables['name'].offset
|
||||
|
||||
format := tf.get_u16() // must be 0
|
||||
assert format == 0
|
||||
count := tf.get_u16()
|
||||
string_offset := tf.get_u16()
|
||||
|
||||
for _ in 0..count {
|
||||
for _ in 0 .. count {
|
||||
platform_id := tf.get_u16()
|
||||
/*platform_specific_id :=*/ tf.get_u16()
|
||||
/*language_id :=*/ tf.get_u16()
|
||||
// platform_specific_id :=
|
||||
tf.get_u16()
|
||||
// language_id :=
|
||||
tf.get_u16()
|
||||
name_id := tf.get_u16()
|
||||
length := tf.get_u16()
|
||||
offset := tf.get_u16()
|
||||
|
@ -709,28 +691,20 @@ fn (mut tf TTF_File) read_name_table() {
|
|||
old_pos := tf.pos
|
||||
tf.pos = table_offset + string_offset + offset
|
||||
|
||||
mut name := ""
|
||||
mut name := ''
|
||||
if platform_id == 0 || platform_id == 3 {
|
||||
name = tf.get_unicode_string(length)
|
||||
} else {
|
||||
name = tf.get_string(length)
|
||||
}
|
||||
//dprintln("Name [${platform_id} / ${platform_specific_id}] id:[$name_id] language:[$language_id] [$name]")
|
||||
// dprintln("Name [${platform_id} / ${platform_specific_id}] id:[$name_id] language:[$language_id] [$name]")
|
||||
tf.pos = old_pos
|
||||
|
||||
match name_id {
|
||||
1 {
|
||||
tf.font_family = name
|
||||
}
|
||||
2 {
|
||||
tf.font_sub_family = name
|
||||
}
|
||||
4 {
|
||||
tf.full_name = name
|
||||
}
|
||||
6 {
|
||||
tf.postscript_name = name
|
||||
}
|
||||
1 { tf.font_family = name }
|
||||
2 { tf.font_sub_family = name }
|
||||
4 { tf.full_name = name }
|
||||
6 { tf.postscript_name = name }
|
||||
else {}
|
||||
}
|
||||
}
|
||||
|
@ -742,9 +716,9 @@ fn (mut tf TTF_File) read_name_table() {
|
|||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) read_cmap_table() {
|
||||
dprintln("*** READ CMAP TABLE ***")
|
||||
assert "cmap" in tf.tables
|
||||
table_offset := tf.tables["cmap"].offset
|
||||
dprintln('*** READ CMAP TABLE ***')
|
||||
assert 'cmap' in tf.tables
|
||||
table_offset := tf.tables['cmap'].offset
|
||||
tf.pos = table_offset
|
||||
|
||||
version := tf.get_u16() // must be 0
|
||||
|
@ -753,7 +727,7 @@ fn (mut tf TTF_File) read_cmap_table() {
|
|||
|
||||
// tables must be sorted by platform id and then platform specific
|
||||
// encoding.
|
||||
for _ in 0..number_sub_tables {
|
||||
for _ in 0 .. number_sub_tables {
|
||||
// platforms are:
|
||||
// 0 - Unicode -- use specific id 6 for full coverage. 0/4 common.
|
||||
// 1 - Macintosh (Discouraged)
|
||||
|
@ -762,7 +736,7 @@ fn (mut tf TTF_File) read_cmap_table() {
|
|||
platform_id := tf.get_u16()
|
||||
platform_specific_id := tf.get_u16()
|
||||
offset := tf.get_u32()
|
||||
dprintln("CMap platform_id=${platform_id} specific_id=${platform_specific_id} offset=${offset}")
|
||||
dprintln('CMap platform_id=$platform_id specific_id=$platform_specific_id offset=$offset')
|
||||
if platform_id == 3 && platform_specific_id <= 1 {
|
||||
tf.read_cmap(table_offset + offset)
|
||||
}
|
||||
|
@ -776,14 +750,14 @@ fn (mut tf TTF_File) read_cmap(offset u32) {
|
|||
length := tf.get_u16()
|
||||
language := tf.get_u16()
|
||||
|
||||
dprintln(" Cmap format: $format length: $length language: $language")
|
||||
dprintln(' Cmap format: $format length: $length language: $language')
|
||||
if format == 0 {
|
||||
dprintln(" Cmap 0 Init...")
|
||||
dprintln(' Cmap 0 Init...')
|
||||
mut cmap := TrueTypeCmap{}
|
||||
cmap.init_0(mut tf)
|
||||
tf.cmaps << cmap
|
||||
} else if format == 4 {
|
||||
dprintln(" Cmap 4 Init...")
|
||||
dprintln(' Cmap 4 Init...')
|
||||
mut cmap := TrueTypeCmap{}
|
||||
cmap.init_4(mut tf)
|
||||
tf.cmaps << cmap
|
||||
|
@ -797,15 +771,15 @@ fn (mut tf TTF_File) read_cmap(offset u32) {
|
|||
* CMAPS 0/4
|
||||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) map_code(char_code int) u16{
|
||||
fn (mut tf TTF_File) map_code(char_code int) u16 {
|
||||
mut index := 0
|
||||
for i in 0..tf.cmaps.len {
|
||||
for i in 0 .. tf.cmaps.len {
|
||||
mut cmap := tf.cmaps[i]
|
||||
if cmap.format == 0 {
|
||||
//dprintln("format 0")
|
||||
// dprintln("format 0")
|
||||
index = cmap.map_0(char_code)
|
||||
} else if cmap.format == 4 {
|
||||
//dprintln("format 4")
|
||||
// dprintln("format 4")
|
||||
index = cmap.map_4(char_code, mut tf)
|
||||
}
|
||||
}
|
||||
|
@ -814,16 +788,16 @@ fn (mut tf TTF_File) map_code(char_code int) u16{
|
|||
|
||||
fn (mut tm TrueTypeCmap) init_0(mut tf TTF_File) {
|
||||
tm.format = 0
|
||||
for i in 0..256 {
|
||||
for i in 0 .. 256 {
|
||||
glyph_index := tf.get_u8()
|
||||
dprintln(" Glyph[$i] = %glyph_index")
|
||||
dprintln(' Glyph[$i] = %glyph_index')
|
||||
tm.arr << glyph_index
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut tm TrueTypeCmap) map_0(char_code int) int {
|
||||
if char_code >= 0 && char_code <= 255 {
|
||||
//dprintln("charCode $char_code maps to ${tm.arr[char_code]}")
|
||||
// dprintln("charCode $char_code maps to ${tm.arr[char_code]}")
|
||||
return tm.arr[char_code]
|
||||
}
|
||||
return 0
|
||||
|
@ -834,13 +808,15 @@ fn (mut tm TrueTypeCmap) init_4(mut tf TTF_File) {
|
|||
|
||||
// 2x segcount
|
||||
seg_count := tf.get_u16() >> 1
|
||||
/*search_range :=*/ tf.get_u16()
|
||||
/*entry_selector :=*/ tf.get_u16()
|
||||
/*range_shift :=*/ tf.get_u16()
|
||||
|
||||
// search_range :=
|
||||
tf.get_u16()
|
||||
// entry_selector :=
|
||||
tf.get_u16()
|
||||
// range_shift :=
|
||||
tf.get_u16()
|
||||
|
||||
// Ending character code for each segment, last is 0xffff
|
||||
for _ in 0..seg_count {
|
||||
for _ in 0 .. seg_count {
|
||||
tm.segments << Segment{0, 0, tf.get_u16(), 0}
|
||||
}
|
||||
|
||||
|
@ -848,17 +824,17 @@ fn (mut tm TrueTypeCmap) init_4(mut tf TTF_File) {
|
|||
tf.get_u16()
|
||||
|
||||
// starting character code for each segment
|
||||
for i in 0..seg_count {
|
||||
for i in 0 .. seg_count {
|
||||
tm.segments[i].start_code = tf.get_u16()
|
||||
}
|
||||
|
||||
// Delta for all character codes in segment
|
||||
for i in 0..seg_count {
|
||||
for i in 0 .. seg_count {
|
||||
tm.segments[i].id_delta = tf.get_u16()
|
||||
}
|
||||
|
||||
// offset in bytes to glyph indexArray, or 0
|
||||
for i in 0..seg_count {
|
||||
for i in 0 .. seg_count {
|
||||
ro := u32(tf.get_u16())
|
||||
if ro != 0 {
|
||||
tm.segments[i].id_range_offset = tf.pos - 2 + ro
|
||||
|
@ -866,26 +842,27 @@ fn (mut tm TrueTypeCmap) init_4(mut tf TTF_File) {
|
|||
tm.segments[i].id_range_offset = 0
|
||||
}
|
||||
}
|
||||
/*
|
||||
/*
|
||||
// DEBUG LOG
|
||||
for i in 0..seg_count {
|
||||
seg := tm.segments[i]
|
||||
dprintln(" segments[$i] = $seg.start_code $seg.end_code $seg.id_delta $seg.id_range_offset")
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
fn (mut tm TrueTypeCmap) map_4(char_code int, mut tf TTF_File) int {
|
||||
//dprintln("HERE map_4 for char [$char_code]")
|
||||
// dprintln("HERE map_4 for char [$char_code]")
|
||||
old_pos := tf.pos
|
||||
if tm.cache[char_code] == -1 {
|
||||
//dprintln("Not found, search for it!")
|
||||
// dprintln("Not found, search for it!")
|
||||
mut found := false
|
||||
for segment in tm.segments {
|
||||
if segment.start_code <= char_code && segment.end_code >= char_code {
|
||||
mut index := (segment.id_delta + char_code) & 0xffff
|
||||
if segment.id_range_offset > 0 {
|
||||
glyph_index_address := segment.id_range_offset + 2 * u32(char_code - segment.start_code)
|
||||
glyph_index_address := segment.id_range_offset +
|
||||
2 * u32(char_code - segment.start_code)
|
||||
tf.pos = glyph_index_address
|
||||
index = tf.get_u16()
|
||||
}
|
||||
|
@ -909,12 +886,13 @@ fn (mut tm TrueTypeCmap) map_4(char_code int, mut tf TTF_File) int {
|
|||
*
|
||||
******************************************************************************/
|
||||
fn (mut tf TTF_File) read_hhea_table() {
|
||||
dprintln("*** READ HHEA TABLE ***")
|
||||
assert "hhea" in tf.tables
|
||||
table_offset := tf.tables["hhea"].offset
|
||||
dprintln('*** READ HHEA TABLE ***')
|
||||
assert 'hhea' in tf.tables
|
||||
table_offset := tf.tables['hhea'].offset
|
||||
tf.pos = table_offset
|
||||
|
||||
/*version :=*/ tf.get_fixed() // 0x00010000
|
||||
// version :=
|
||||
tf.get_fixed() // 0x00010000
|
||||
|
||||
tf.ascent = tf.get_fword()
|
||||
tf.descent = tf.get_fword()
|
||||
|
@ -957,14 +935,14 @@ fn (mut kt Kern0Table) get(glyph_index int) (int, int) {
|
|||
|
||||
if kt.old_index >= 0 {
|
||||
ch := ((u32(kt.old_index & 0xFFFF) << 16) | u32(glyph_index & 0xFFFF))
|
||||
//dprintln("kern_get: $ch")
|
||||
// dprintln("kern_get: $ch")
|
||||
if ch in kt.kmap {
|
||||
x = int(kt.kmap[ch])
|
||||
}
|
||||
}
|
||||
kt.old_index = glyph_index
|
||||
if kt.swap {
|
||||
return 0 , x
|
||||
return 0, x
|
||||
}
|
||||
return x, 0
|
||||
}
|
||||
|
@ -975,7 +953,7 @@ fn (mut tf TTF_File) create_kern_table0(vertical bool, cross bool) Kern0Table {
|
|||
search_range := tf.get_u16()
|
||||
entry_selector := tf.get_u16()
|
||||
range_shift := tf.get_u16()
|
||||
dprintln("n_pairs: $n_pairs search_range: $search_range entry_selector: $entry_selector range_shift: $range_shift")
|
||||
dprintln('n_pairs: $n_pairs search_range: $search_range entry_selector: $entry_selector range_shift: $range_shift')
|
||||
|
||||
mut kt0 := Kern0Table{
|
||||
swap: (vertical && !cross) || (!vertical && cross)
|
||||
|
@ -983,61 +961,61 @@ fn (mut tf TTF_File) create_kern_table0(vertical bool, cross bool) Kern0Table {
|
|||
n_pairs: n_pairs
|
||||
}
|
||||
|
||||
for _ in 0..n_pairs {
|
||||
for _ in 0 .. n_pairs {
|
||||
left := tf.get_u16()
|
||||
right := tf.get_u16()
|
||||
value := tf.get_fword()
|
||||
tmp_index := (u32(left) << 16) | u32(right)
|
||||
kt0.kmap[tmp_index] = value
|
||||
//dprintln("index: ${tmp_index.hex()} val: ${value.hex()}")
|
||||
// dprintln("index: ${tmp_index.hex()} val: ${value.hex()}")
|
||||
}
|
||||
kt0.old_index = -1
|
||||
return kt0
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) read_kern_table() {
|
||||
dprintln("*** READ KERN TABLE ***")
|
||||
if !("kern" in tf.tables){
|
||||
dprintln('*** READ KERN TABLE ***')
|
||||
if !('kern' in tf.tables) {
|
||||
return
|
||||
}
|
||||
table_offset := tf.tables["kern"].offset
|
||||
table_offset := tf.tables['kern'].offset
|
||||
tf.pos = table_offset
|
||||
|
||||
version := tf.get_u16() // must be 0
|
||||
assert version == 0 // must be 0
|
||||
n_tables := tf.get_u16()
|
||||
|
||||
dprintln("Kern Table version: $version Kern nTables: $n_tables")
|
||||
dprintln('Kern Table version: $version Kern nTables: $n_tables')
|
||||
|
||||
for _ in 0..n_tables{
|
||||
for _ in 0 .. n_tables {
|
||||
st_version := tf.get_u16() // sub table version
|
||||
length := tf.get_u16()
|
||||
coverage := tf.get_u16()
|
||||
format := coverage >> 8
|
||||
cross := coverage & 4
|
||||
vertical := (coverage & 0x1) == 0
|
||||
dprintln("Kerning subtable version [$st_version] format [$format] length [$length] coverage: [${coverage.hex()}]")
|
||||
dprintln('Kerning subtable version [$st_version] format [$format] length [$length] coverage: [$coverage.hex()]')
|
||||
if format == 0 {
|
||||
dprintln("kern format: 0")
|
||||
dprintln('kern format: 0')
|
||||
kern := tf.create_kern_table0(vertical, cross != 0)
|
||||
tf.kern << kern
|
||||
} else {
|
||||
dprintln("Unknown format -- skip")
|
||||
dprintln('Unknown format -- skip')
|
||||
tf.pos = tf.pos + length
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) reset_kern() {
|
||||
for i in 0..tf.kern.len {
|
||||
for i in 0 .. tf.kern.len {
|
||||
tf.kern[i].reset()
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut tf TTF_File) next_kern(glyph_index int) (int, int){
|
||||
fn (mut tf TTF_File) next_kern(glyph_index int) (int, int) {
|
||||
mut x := 0
|
||||
mut y := 0
|
||||
for i in 0..tf.kern.len {
|
||||
for i in 0 .. tf.kern.len {
|
||||
tmp_x, tmp_y := tf.kern[i].get(glyph_index)
|
||||
x = x + tmp_x
|
||||
y = y + tmp_y
|
||||
|
@ -1045,29 +1023,27 @@ fn (mut tf TTF_File) next_kern(glyph_index int) (int, int){
|
|||
return x, y
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* TTF_File Utility
|
||||
*
|
||||
******************************************************************************/
|
||||
pub
|
||||
fn (tf TTF_File) get_info_string() string{
|
||||
txt := "----- Font Info -----
|
||||
pub fn (tf TTF_File) get_info_string() string {
|
||||
txt := '----- Font Info -----
|
||||
font_family : $tf.font_family
|
||||
font_sub_family : $tf.font_sub_family
|
||||
full_name : $tf.full_name
|
||||
postscript_name : $tf.postscript_name
|
||||
version : $tf.version
|
||||
font_revision : $tf.font_revision
|
||||
magic_number : ${tf.magic_number.hex()}
|
||||
flags : ${tf.flags.hex()}
|
||||
created unixTS : ${tf.created}
|
||||
modified unixTS : ${tf.modified}
|
||||
box : [x_min:${tf.x_min}, y_min:${tf.y_min}, x_Max:${tf.x_max}, y_Max:${tf.y_max}]
|
||||
mac_style : ${tf.mac_style}
|
||||
magic_number : $tf.magic_number.hex()
|
||||
flags : $tf.flags.hex()
|
||||
created unixTS : $tf.created
|
||||
modified unixTS : $tf.modified
|
||||
box : [x_min:$tf.x_min, y_min:$tf.y_min, x_Max:$tf.x_max, y_Max:$tf.y_max]
|
||||
mac_style : $tf.mac_style
|
||||
-----------------------
|
||||
"
|
||||
'
|
||||
return txt
|
||||
}
|
||||
|
||||
|
@ -1076,24 +1052,34 @@ mac_style : ${tf.mac_style}
|
|||
* TTF_File test
|
||||
*
|
||||
******************************************************************************/
|
||||
fn tst(){
|
||||
fn tst() {
|
||||
mut tf := TTF_File{}
|
||||
|
||||
tf.buf = [
|
||||
byte(0xFF), // 8 bit
|
||||
0xF1, 0xF2, // 16 bit
|
||||
0x81, 0x23, 0x45, 0x67, // 32 bit
|
||||
0x12, 0x34, 0x12, 0x34, // get_2dot14 16 bit
|
||||
0x12, 0x34, 0x12, 0x34 // get_fixed 32 bit int
|
||||
byte(0xFF), /* 8 bit */
|
||||
0xF1,
|
||||
0xF2, /* 16 bit */
|
||||
0x81,
|
||||
0x23,
|
||||
0x45,
|
||||
0x67, /* 32 bit */
|
||||
0x12,
|
||||
0x34,
|
||||
0x12,
|
||||
0x34, /* get_2dot14 16 bit */
|
||||
0x12,
|
||||
0x34,
|
||||
0x12,
|
||||
0x34 /* get_fixed 32 bit int */,
|
||||
]
|
||||
assert tf.get_u8().hex() == "ff"
|
||||
assert tf.get_u16().hex() == "f1f2"
|
||||
assert tf.get_u32().hex() == "81234567"
|
||||
assert tf.get_u8().hex() == 'ff'
|
||||
assert tf.get_u16().hex() == 'f1f2'
|
||||
assert tf.get_u32().hex() == '81234567'
|
||||
|
||||
dprintln("buf len: ${tf.buf.len}")
|
||||
//dprintln( tf.get_u8().hex() )
|
||||
//dprintln( tf.get_u16().hex() )
|
||||
//dprintln( tf.get_u32().hex() )
|
||||
//dprintln( tf.get_2dot14() )
|
||||
//dprintln( tf.get_fixed() )
|
||||
dprintln('buf len: $tf.buf.len')
|
||||
// dprintln( tf.get_u8().hex() )
|
||||
// dprintln( tf.get_u16().hex() )
|
||||
// dprintln( tf.get_u32().hex() )
|
||||
// dprintln( tf.get_2dot14() )
|
||||
// dprintln( tf.get_fixed() )
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -171,21 +171,27 @@ fn (mut ws Client) send_message_event(msg &Message) {
|
|||
ws.debug_log('sending on_message event')
|
||||
for ev_handler in ws.message_callbacks {
|
||||
if !ev_handler.is_ref {
|
||||
ev_handler.handler(ws, msg)
|
||||
ev_handler.handler(ws, msg) or { ws.logger.error('send_message_event error: $err') }
|
||||
} else {
|
||||
ev_handler.handler2(ws, msg, ev_handler.ref)
|
||||
ev_handler.handler2(ws, msg, ev_handler.ref) or {
|
||||
ws.logger.error('send_message_event error: $err')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send_error_event invokes the on_error callback
|
||||
fn (mut ws Client) send_error_event(err string) {
|
||||
fn (mut ws Client) send_error_event(error string) {
|
||||
ws.debug_log('sending on_error event')
|
||||
for ev_handler in ws.error_callbacks {
|
||||
if !ev_handler.is_ref {
|
||||
ev_handler.handler(mut ws, err)
|
||||
ev_handler.handler(mut ws, error) or {
|
||||
ws.logger.error('send_error_event error: $error, err: $err')
|
||||
}
|
||||
} else {
|
||||
ev_handler.handler2(mut ws, err, ev_handler.ref)
|
||||
ev_handler.handler2(mut ws, error, ev_handler.ref) or {
|
||||
ws.logger.error('send_error_event error: $error, err: $err')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -195,9 +201,13 @@ fn (mut ws Client) send_close_event(code int, reason string) {
|
|||
ws.debug_log('sending on_close event')
|
||||
for ev_handler in ws.close_callbacks {
|
||||
if !ev_handler.is_ref {
|
||||
ev_handler.handler(mut ws, code, reason)
|
||||
ev_handler.handler(mut ws, code, reason) or {
|
||||
ws.logger.error('send_close_event error: $err')
|
||||
}
|
||||
} else {
|
||||
ev_handler.handler2(mut ws, code, reason, ev_handler.ref)
|
||||
ev_handler.handler2(mut ws, code, reason, ev_handler.ref) or {
|
||||
ws.logger.error('send_close_event error: $err')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,9 +217,11 @@ fn (mut ws Client) send_open_event() {
|
|||
ws.debug_log('sending on_open event')
|
||||
for ev_handler in ws.open_callbacks {
|
||||
if !ev_handler.is_ref {
|
||||
ev_handler.handler(mut ws)
|
||||
ev_handler.handler(mut ws) or { ws.logger.error('send_open_event error: $err') }
|
||||
} else {
|
||||
ev_handler.handler2(mut ws, ev_handler.ref)
|
||||
ev_handler.handler2(mut ws, ev_handler.ref) or {
|
||||
ws.logger.error('send_open_event error: $err')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ const (
|
|||
// validate_client validates client frame rules from RFC6455
|
||||
pub fn (mut ws Client) validate_frame(frame &Frame) ? {
|
||||
if frame.rsv1 || frame.rsv2 || frame.rsv3 {
|
||||
ws.close(1002, 'rsv cannot be other than 0, not negotiated')
|
||||
ws.close(1002, 'rsv cannot be other than 0, not negotiated') ?
|
||||
return error('rsv cannot be other than 0, not negotiated')
|
||||
}
|
||||
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7)
|
||||
|
@ -113,7 +113,7 @@ fn (mut ws Client) validate_utf_8(opcode OPCode, payload []byte) ? {
|
|||
if opcode in [.text_frame, .close] && !utf8.validate(payload.data, payload.len) {
|
||||
ws.logger.error('malformed utf8 payload, payload len: ($payload.len)')
|
||||
ws.send_error_event('Recieved malformed utf8.')
|
||||
ws.close(1007, 'malformed utf8 payload')
|
||||
ws.close(1007, 'malformed utf8 payload') ?
|
||||
return error('malformed utf8 payload')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ pub fn (mut ws Client) listen() ? {
|
|||
defer {
|
||||
ws.logger.info('Quit client listener, server($ws.is_server)...')
|
||||
if ws.state == .open {
|
||||
ws.close(1000, 'closed by client')
|
||||
ws.close(1000, 'closed by client') or { }
|
||||
}
|
||||
}
|
||||
for ws.state == .open {
|
||||
|
@ -243,10 +243,6 @@ pub fn (mut ws Client) write_ptr(bytes byteptr, payload_len int, code OPCode) ?
|
|||
mut header := []byte{len: header_len, init: `0`} // [`0`].repeat(header_len)
|
||||
header[0] = byte(int(code)) | 0x80
|
||||
masking_key := create_masking_key()
|
||||
defer {
|
||||
unsafe {
|
||||
}
|
||||
}
|
||||
if ws.is_server {
|
||||
if payload_len <= 125 {
|
||||
header[1] = byte(payload_len)
|
||||
|
@ -315,7 +311,7 @@ pub fn (mut ws Client) write(bytes []byte, code OPCode) ? {
|
|||
|
||||
// write_str, writes a string with a websocket texttype to socket
|
||||
pub fn (mut ws Client) write_str(str string) ? {
|
||||
ws.write_ptr(str.str, str.len, .text_frame)
|
||||
ws.write_ptr(str.str, str.len, .text_frame) ?
|
||||
}
|
||||
|
||||
// close closes the websocket connection
|
||||
|
@ -328,7 +324,7 @@ pub fn (mut ws Client) close(code int, message string) ? {
|
|||
return ret_err
|
||||
}
|
||||
defer {
|
||||
ws.shutdown_socket()
|
||||
ws.shutdown_socket() or { }
|
||||
ws.reset_state()
|
||||
}
|
||||
ws.set_state(.closing)
|
||||
|
|
|
@ -30,7 +30,7 @@ fn start_server() ? {
|
|||
}) ?
|
||||
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
|
||||
match msg.opcode {
|
||||
.pong { ws.write_str('pong') }
|
||||
.pong { ws.write_str('pong') or { panic(err) } }
|
||||
else { ws.write(msg.payload, msg.opcode) or { panic(err) } }
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue