gg,sokol,stbi,gx,fontstash: cleanup for -Wimpure-v
							parent
							
								
									8fbd8f790d
								
							
						
					
					
						commit
						576664e31f
					
				|  | @ -46,7 +46,6 @@ const ( | |||
| 		'vlib/regex/regex_test.v' /* contains meaningfull formatting of the test case data */, | ||||
| 		'vlib/readline/readline_test.v' /* vfmt eats `{ Readline }` from `import readline { Readline }` */, | ||||
| 		'vlib/glm/glm.v' /* `mut res &f32` => `mut res f32`, which then fails to compile */, | ||||
| 		'vlib/fontstash/fontstash_structs.v' /* eats fn arg names for inline callback types in struct field declarations */, | ||||
| 		'vlib/crypto/sha512/sha512block_generic.v' /* formatting of large constant arrays wraps to too many lines */, | ||||
| 		'vlib/crypto/aes/const.v' /* formatting of large constant arrays wraps to too many lines */, | ||||
| 	]) | ||||
|  |  | |||
|  | @ -0,0 +1,51 @@ | |||
| module fontstash | ||||
| 
 | ||||
| pub struct C.FONSparams { | ||||
| 	width   int | ||||
| 	height  int | ||||
| 	flags   char | ||||
| 	userPtr voidptr | ||||
| 	// int (*renderCreate)(void* uptr, int width, int height)
 | ||||
| 	renderCreate fn (uptr voidptr, width int, height int) int | ||||
| 	// int (*renderResize)(void* uptr, int width, int height)
 | ||||
| 	renderResize fn (uptr voidptr, width int, height int) int | ||||
| 	// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
 | ||||
| 	renderUpdate fn (uptr voidptr, rect &int, data &byte) | ||||
| 	// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
 | ||||
| 	renderDraw fn (uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) | ||||
| 	// void (*renderDelete)(void* uptr)
 | ||||
| 	renderDelete fn (uptr voidptr) | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONSquad { | ||||
| 	x0 f32 | ||||
| 	y0 f32 | ||||
| 	s0 f32 | ||||
| 	t0 f32 | ||||
| 	x1 f32 | ||||
| 	y1 f32 | ||||
| 	s1 f32 | ||||
| 	t1 f32 | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONStextIter { | ||||
| 	x              f32 | ||||
| 	y              f32 | ||||
| 	nextx          f32 | ||||
| 	nexty          f32 | ||||
| 	scale          f32 | ||||
| 	spacing        f32 | ||||
| 	codepoint      u32 | ||||
| 	isize          i16 | ||||
| 	iblur          i16 | ||||
| 	font           &C.FONSfont | ||||
| 	prevGlyphIndex int | ||||
| 	str            &byte | ||||
| 	next           &byte | ||||
| 	end            &byte | ||||
| 	utf8state      u32 | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONSfont {} | ||||
| 
 | ||||
| pub struct C.FONScontext {} | ||||
|  | @ -27,54 +27,3 @@ pub enum FonsErrorCode { | |||
| 	// Trying to pop too many states fonsPopState().
 | ||||
| 	states_underflow = 4 | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONSparams { | ||||
| 	width int | ||||
| 	height int | ||||
| 	flags char | ||||
| 	userPtr voidptr | ||||
| 	// int (*renderCreate)(void* uptr, int width, int height)
 | ||||
| 	renderCreate fn(uptr voidptr, width int, height int) int | ||||
| 	// int (*renderResize)(void* uptr, int width, int height)
 | ||||
| 	renderResize fn(uptr voidptr, width int, height int) int | ||||
| 	// void (*renderUpdate)(void* uptr, int* rect, const unsigned char* data)
 | ||||
| 	renderUpdate fn(uptr voidptr, rect &int, data byteptr) | ||||
| 	// void (*renderDraw)(void* uptr, const float* verts, const float* tcoords, const unsigned int* colors, int nverts)
 | ||||
| 	renderDraw fn(uptr voidptr, verts &f32, tcoords &f32, colors &u32, nverts int) | ||||
| 	// void (*renderDelete)(void* uptr)
 | ||||
| 	renderDelete fn(uptr voidptr) | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONSquad | ||||
| { | ||||
| 	x0 f32 | ||||
| 	y0 f32 | ||||
| 	s0 f32 | ||||
| 	t0 f32 | ||||
| 	x1 f32 | ||||
| 	y1 f32 | ||||
| 	s1 f32 | ||||
| 	t1 f32 | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONStextIter { | ||||
| 	x f32 | ||||
| 	y f32 | ||||
| 	nextx f32 | ||||
| 	nexty f32 | ||||
| 	scale f32 | ||||
| 	spacing f32 | ||||
| 	codepoint u32 | ||||
| 	isize i16 | ||||
| 	iblur i16 | ||||
| 	font &C.FONSfont | ||||
| 	prevGlyphIndex int | ||||
| 	str byteptr | ||||
| 	next byteptr | ||||
| 	end byteptr | ||||
| 	utf8state u32 | ||||
| } | ||||
| 
 | ||||
| pub struct C.FONSfont {} | ||||
| 
 | ||||
| pub struct C.FONScontext {} | ||||
|  |  | |||
|  | @ -0,0 +1,278 @@ | |||
| // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
 | ||||
| // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
 | ||||
| 
 | ||||
| module gg | ||||
| 
 | ||||
| import os | ||||
| import gx | ||||
| import sokol | ||||
| import sokol.sapp | ||||
| import sokol.sgl | ||||
| import sokol.gfx | ||||
| import math | ||||
| 
 | ||||
| pub struct Event { | ||||
| pub mut: | ||||
| 	frame_count        u64 | ||||
| 	typ                sapp.EventType | ||||
| 	key_code           KeyCode | ||||
| 	char_code          u32 | ||||
| 	key_repeat         bool | ||||
| 	modifiers          u32 | ||||
| 	mouse_button       MouseButton | ||||
| 	mouse_x            f32 | ||||
| 	mouse_y            f32 | ||||
| 	mouse_dx           f32 | ||||
| 	mouse_dy           f32 | ||||
| 	scroll_x           f32 | ||||
| 	scroll_y           f32 | ||||
| 	num_touches        int | ||||
| 	touches            [8]C.sapp_touchpoint | ||||
| 	window_width       int | ||||
| 	window_height      int | ||||
| 	framebuffer_width  int | ||||
| 	framebuffer_height int | ||||
| } | ||||
| 
 | ||||
| [heap] | ||||
| pub struct Context { | ||||
| mut: | ||||
| 	render_text bool = true | ||||
| 	// a cache with all images created by the user. used for sokol image init and to save space
 | ||||
| 	// (so that the user can store image ids, not entire Image objects)
 | ||||
| 	image_cache   []Image | ||||
| 	needs_refresh bool = true | ||||
| 	ticks         int // for ui mode only
 | ||||
| pub: | ||||
| 	native_rendering bool | ||||
| pub mut: | ||||
| 	scale f32 = 1.0 | ||||
| 	// will get set to 2.0 for retina, will remain 1.0 for normal
 | ||||
| 	width       int | ||||
| 	height      int | ||||
| 	clear_pass  C.sg_pass_action | ||||
| 	window      C.sapp_desc | ||||
| 	timage_pip  C.sgl_pipeline | ||||
| 	config      Config | ||||
| 	ft          &FT | ||||
| 	font_inited bool | ||||
| 	ui_mode     bool // do not redraw everything 60 times/second, but only when the user requests
 | ||||
| 	frame       u64  // the current frame counted from the start of the application; always increasing
 | ||||
| 	//
 | ||||
| 	mbtn_mask     byte | ||||
| 	mouse_buttons MouseButtons // typed version of mbtn_mask; easier to use for user programs
 | ||||
| 	mouse_pos_x   int | ||||
| 	mouse_pos_y   int | ||||
| 	mouse_dx      int | ||||
| 	mouse_dy      int | ||||
| 	scroll_x      int | ||||
| 	scroll_y      int | ||||
| 	//
 | ||||
| 	key_modifiers     Modifier // the current key modifiers
 | ||||
| 	key_repeat        bool     // whether the pressed key was an autorepeated one
 | ||||
| 	pressed_keys      [key_code_max]bool // an array representing all currently pressed keys
 | ||||
| 	pressed_keys_edge [key_code_max]bool // true when the previous state of pressed_keys,
 | ||||
| 	// *before* the current event was different
 | ||||
| } | ||||
| 
 | ||||
| fn gg_init_sokol_window(user_data voidptr) { | ||||
| 	mut g := unsafe { &Context(user_data) } | ||||
| 	desc := sapp.create_desc() | ||||
| 	/* | ||||
| 	desc := C.sg_desc{ | ||||
| 		mtl_device: sapp.metal_get_device() | ||||
| 		mtl_renderpass_descriptor_cb: sapp.metal_get_renderpass_descriptor | ||||
| 		mtl_drawable_cb: sapp.metal_get_drawable | ||||
| 		d3d11_device: sapp.d3d11_get_device() | ||||
| 		d3d11_device_context: sapp.d3d11_get_device_context() | ||||
| 		d3d11_render_target_view_cb: sapp.d3d11_get_render_target_view | ||||
| 		d3d11_depth_stencil_view_cb: sapp.d3d11_get_depth_stencil_view | ||||
| 	} | ||||
| 	*/ | ||||
| 	gfx.setup(&desc) | ||||
| 	sgl_desc := C.sgl_desc_t{} | ||||
| 	sgl.setup(&sgl_desc) | ||||
| 	g.scale = dpi_scale() | ||||
| 	// is_high_dpi := sapp.high_dpi()
 | ||||
| 	// fb_w := sapp.width()
 | ||||
| 	// fb_h := sapp.height()
 | ||||
| 	// println('g.scale=$g.scale is_high_dpi=$is_high_dpi fb_w=$fb_w fb_h=$fb_h')
 | ||||
| 	// if g.config.init_text {
 | ||||
| 	// `os.is_file()` won't work on Android if the font file is embedded into the APK
 | ||||
| 	exists := $if !android { os.is_file(g.config.font_path) } $else { true } | ||||
| 	if g.config.font_path != '' && !exists { | ||||
| 		g.render_text = false | ||||
| 	} else if g.config.font_path != '' && exists { | ||||
| 		// t := time.ticks()
 | ||||
| 		g.ft = new_ft( | ||||
| 			font_path: g.config.font_path | ||||
| 			custom_bold_font_path: g.config.custom_bold_font_path | ||||
| 			scale: dpi_scale() | ||||
| 		) or { panic(err) } | ||||
| 		// println('FT took ${time.ticks()-t} ms')
 | ||||
| 		g.font_inited = true | ||||
| 	} else { | ||||
| 		if g.config.font_bytes_normal.len > 0 { | ||||
| 			g.ft = new_ft( | ||||
| 				bytes_normal: g.config.font_bytes_normal | ||||
| 				bytes_bold: g.config.font_bytes_bold | ||||
| 				bytes_mono: g.config.font_bytes_mono | ||||
| 				bytes_italic: g.config.font_bytes_italic | ||||
| 				scale: sapp.dpi_scale() | ||||
| 			) or { panic(err) } | ||||
| 			g.font_inited = true | ||||
| 		} else { | ||||
| 			sfont := system_font_path() | ||||
| 			if g.config.font_path != '' { | ||||
| 				eprintln('font file "$g.config.font_path" does not exist, the system font ($sfont) was used instead.') | ||||
| 			} | ||||
| 
 | ||||
| 			g.ft = new_ft( | ||||
| 				font_path: sfont | ||||
| 				custom_bold_font_path: g.config.custom_bold_font_path | ||||
| 				scale: sapp.dpi_scale() | ||||
| 			) or { panic(err) } | ||||
| 			g.font_inited = true | ||||
| 		} | ||||
| 	} | ||||
| 	//
 | ||||
| 	mut pipdesc := C.sg_pipeline_desc{ | ||||
| 		label: c'alpha_image' | ||||
| 	} | ||||
| 	unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) } | ||||
| 
 | ||||
| 	color_state := C.sg_color_state{ | ||||
| 		blend: C.sg_blend_state{ | ||||
| 			enabled: true | ||||
| 			src_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_SRC_ALPHA) | ||||
| 			dst_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA) | ||||
| 		} | ||||
| 	} | ||||
| 	pipdesc.colors[0] = color_state | ||||
| 
 | ||||
| 	g.timage_pip = sgl.make_pipeline(&pipdesc) | ||||
| 	//
 | ||||
| 	if g.config.init_fn != voidptr(0) { | ||||
| 		g.config.init_fn(g.config.user_data) | ||||
| 	} | ||||
| 	// Create images now that we can do that after sg is inited
 | ||||
| 	if g.native_rendering { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for i in 0 .. g.image_cache.len { | ||||
| 		if g.image_cache[i].simg.id == 0 { | ||||
| 			g.image_cache[i].init_sokol_image() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| pub fn new_context(cfg Config) &Context { | ||||
| 	mut g := &Context{ | ||||
| 		width: cfg.width | ||||
| 		height: cfg.height | ||||
| 		config: cfg | ||||
| 		ft: 0 | ||||
| 		ui_mode: cfg.ui_mode | ||||
| 		native_rendering: cfg.native_rendering | ||||
| 	} | ||||
| 	g.set_bg_color(cfg.bg_color) | ||||
| 	// C.printf('new_context() %p\n', cfg.user_data)
 | ||||
| 	window := C.sapp_desc{ | ||||
| 		user_data: g | ||||
| 		init_userdata_cb: gg_init_sokol_window | ||||
| 		frame_userdata_cb: gg_frame_fn | ||||
| 		event_userdata_cb: gg_event_fn | ||||
| 		fail_userdata_cb: gg_fail_fn | ||||
| 		cleanup_userdata_cb: gg_cleanup_fn | ||||
| 		window_title: &char(cfg.window_title.str) | ||||
| 		html5_canvas_name: &char(cfg.window_title.str) | ||||
| 		width: cfg.width | ||||
| 		height: cfg.height | ||||
| 		sample_count: cfg.sample_count | ||||
| 		high_dpi: true | ||||
| 		fullscreen: cfg.fullscreen | ||||
| 		__v_native_render: cfg.native_rendering | ||||
| 	} | ||||
| 	g.window = window | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), r, c) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if c.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	sgl.c4b(c.r, c.g, c.b, c.a) | ||||
| 	nx := x * ctx.scale | ||||
| 	ny := y * ctx.scale | ||||
| 	nr := r * ctx.scale | ||||
| 	mut theta := f32(0) | ||||
| 	mut xx := f32(0) | ||||
| 	mut yy := f32(0) | ||||
| 	sgl.begin_line_strip() | ||||
| 	for i := 0; i < segments + 1; i++ { | ||||
| 		theta = 2.0 * f32(math.pi) * f32(i) / f32(segments) | ||||
| 		xx = nr * math.cosf(theta) | ||||
| 		yy = nr * math.sinf(theta) | ||||
| 		sgl.v2f(xx + nx, yy + ny) | ||||
| 	} | ||||
| 	sgl.end() | ||||
| } | ||||
| 
 | ||||
| pub fn high_dpi() bool { | ||||
| 	return C.sapp_high_dpi() | ||||
| } | ||||
| 
 | ||||
| pub fn screen_size() Size { | ||||
| 	$if macos { | ||||
| 		return C.gg_get_screen_size() | ||||
| 	} | ||||
| 	// TODO windows, linux, etc
 | ||||
| 	return Size{} | ||||
| } | ||||
| 
 | ||||
| fn C.WaitMessage() | ||||
| 
 | ||||
| /* | ||||
| pub fn wait_events() { | ||||
| 	unsafe { | ||||
| 		$if macos { | ||||
| 			#NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny | ||||
| 			#untilDate:[NSDate distantFuture] | ||||
| 			#inMode:NSDefaultRunLoopMode | ||||
| 			#dequeue:YES]; | ||||
| 			#[NSApp sendEvent:event]; | ||||
| 		} | ||||
| 		$if windows { | ||||
| 			C.WaitMessage() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| */ | ||||
| 
 | ||||
| // TODO: Fix alpha
 | ||||
| pub fn (ctx &Context) draw_rect(x f32, y f32, w f32, h f32, c gx.Color) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			C.darwin_draw_rect(x, ctx.height - (y + h), w, h, c) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if c.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	sgl.c4b(c.r, c.g, c.b, c.a) | ||||
| 	sgl.begin_quads() | ||||
| 	sgl.v2f(x * ctx.scale, y * ctx.scale) | ||||
| 	sgl.v2f((x + w) * ctx.scale, y * ctx.scale) | ||||
| 	sgl.v2f((x + w) * ctx.scale, (y + h) * ctx.scale) | ||||
| 	sgl.v2f(x * ctx.scale, (y + h) * ctx.scale) | ||||
| 	sgl.end() | ||||
| } | ||||
							
								
								
									
										268
									
								
								vlib/gg/gg.v
								
								
								
								
							
							
						
						
									
										268
									
								
								vlib/gg/gg.v
								
								
								
								
							|  | @ -3,9 +3,7 @@ | |||
| 
 | ||||
| module gg | ||||
| 
 | ||||
| import os | ||||
| import gx | ||||
| import sokol | ||||
| import sokol.sapp | ||||
| import sokol.sgl | ||||
| import sokol.gfx | ||||
|  | @ -29,29 +27,6 @@ pub type FNUnClick = fn (x f32, y f32, button MouseButton, data voidptr) | |||
| 
 | ||||
| pub type FNChar = fn (c u32, data voidptr) | ||||
| 
 | ||||
| pub struct Event { | ||||
| pub mut: | ||||
| 	frame_count        u64 | ||||
| 	typ                sapp.EventType | ||||
| 	key_code           KeyCode | ||||
| 	char_code          u32 | ||||
| 	key_repeat         bool | ||||
| 	modifiers          u32 | ||||
| 	mouse_button       MouseButton | ||||
| 	mouse_x            f32 | ||||
| 	mouse_y            f32 | ||||
| 	mouse_dx           f32 | ||||
| 	mouse_dy           f32 | ||||
| 	scroll_x           f32 | ||||
| 	scroll_y           f32 | ||||
| 	num_touches        int | ||||
| 	touches            [8]C.sapp_touchpoint | ||||
| 	window_width       int | ||||
| 	window_height      int | ||||
| 	framebuffer_width  int | ||||
| 	framebuffer_height int | ||||
| } | ||||
| 
 | ||||
| pub struct Config { | ||||
| pub: | ||||
| 	width         int | ||||
|  | @ -110,145 +85,12 @@ pub struct PenConfig { | |||
| 	thickness int = 1 | ||||
| } | ||||
| 
 | ||||
| [heap] | ||||
| pub struct Context { | ||||
| mut: | ||||
| 	render_text bool = true | ||||
| 	// a cache with all images created by the user. used for sokol image init and to save space
 | ||||
| 	// (so that the user can store image ids, not entire Image objects)
 | ||||
| 	image_cache   []Image | ||||
| 	needs_refresh bool = true | ||||
| 	ticks         int // for ui mode only
 | ||||
| pub: | ||||
| 	native_rendering bool | ||||
| pub mut: | ||||
| 	scale f32 = 1.0 | ||||
| 	// will get set to 2.0 for retina, will remain 1.0 for normal
 | ||||
| 	width       int | ||||
| 	height      int | ||||
| 	clear_pass  C.sg_pass_action | ||||
| 	window      C.sapp_desc | ||||
| 	timage_pip  C.sgl_pipeline | ||||
| 	config      Config | ||||
| 	ft          &FT | ||||
| 	font_inited bool | ||||
| 	ui_mode     bool // do not redraw everything 60 times/second, but only when the user requests
 | ||||
| 	frame       u64  // the current frame counted from the start of the application; always increasing
 | ||||
| 	//
 | ||||
| 	mbtn_mask     byte | ||||
| 	mouse_buttons MouseButtons // typed version of mbtn_mask; easier to use for user programs
 | ||||
| 	mouse_pos_x   int | ||||
| 	mouse_pos_y   int | ||||
| 	mouse_dx      int | ||||
| 	mouse_dy      int | ||||
| 	scroll_x      int | ||||
| 	scroll_y      int | ||||
| 	//
 | ||||
| 	key_modifiers     Modifier // the current key modifiers
 | ||||
| 	key_repeat        bool     // whether the pressed key was an autorepeated one
 | ||||
| 	pressed_keys      [key_code_max]bool // an array representing all currently pressed keys
 | ||||
| 	pressed_keys_edge [key_code_max]bool // true when the previous state of pressed_keys,
 | ||||
| 	// *before* the current event was different
 | ||||
| } | ||||
| 
 | ||||
| pub struct Size { | ||||
| pub: | ||||
| 	width  int | ||||
| 	height int | ||||
| } | ||||
| 
 | ||||
| fn gg_init_sokol_window(user_data voidptr) { | ||||
| 	mut g := unsafe { &Context(user_data) } | ||||
| 	desc := sapp.create_desc() | ||||
| 	/* | ||||
| 	desc := C.sg_desc{ | ||||
| 		mtl_device: sapp.metal_get_device() | ||||
| 		mtl_renderpass_descriptor_cb: sapp.metal_get_renderpass_descriptor | ||||
| 		mtl_drawable_cb: sapp.metal_get_drawable | ||||
| 		d3d11_device: sapp.d3d11_get_device() | ||||
| 		d3d11_device_context: sapp.d3d11_get_device_context() | ||||
| 		d3d11_render_target_view_cb: sapp.d3d11_get_render_target_view | ||||
| 		d3d11_depth_stencil_view_cb: sapp.d3d11_get_depth_stencil_view | ||||
| 	} | ||||
| 	*/ | ||||
| 	gfx.setup(&desc) | ||||
| 	sgl_desc := C.sgl_desc_t{} | ||||
| 	sgl.setup(&sgl_desc) | ||||
| 	g.scale = dpi_scale() | ||||
| 	// is_high_dpi := sapp.high_dpi()
 | ||||
| 	// fb_w := sapp.width()
 | ||||
| 	// fb_h := sapp.height()
 | ||||
| 	// println('g.scale=$g.scale is_high_dpi=$is_high_dpi fb_w=$fb_w fb_h=$fb_h')
 | ||||
| 	// if g.config.init_text {
 | ||||
| 	// `os.is_file()` won't work on Android if the font file is embedded into the APK
 | ||||
| 	exists := $if !android { os.is_file(g.config.font_path) } $else { true } | ||||
| 	if g.config.font_path != '' && !exists { | ||||
| 		g.render_text = false | ||||
| 	} else if g.config.font_path != '' && exists { | ||||
| 		// t := time.ticks()
 | ||||
| 		g.ft = new_ft( | ||||
| 			font_path: g.config.font_path | ||||
| 			custom_bold_font_path: g.config.custom_bold_font_path | ||||
| 			scale: dpi_scale() | ||||
| 		) or { panic(err) } | ||||
| 		// println('FT took ${time.ticks()-t} ms')
 | ||||
| 		g.font_inited = true | ||||
| 	} else { | ||||
| 		if g.config.font_bytes_normal.len > 0 { | ||||
| 			g.ft = new_ft( | ||||
| 				bytes_normal: g.config.font_bytes_normal | ||||
| 				bytes_bold: g.config.font_bytes_bold | ||||
| 				bytes_mono: g.config.font_bytes_mono | ||||
| 				bytes_italic: g.config.font_bytes_italic | ||||
| 				scale: sapp.dpi_scale() | ||||
| 			) or { panic(err) } | ||||
| 			g.font_inited = true | ||||
| 		} else { | ||||
| 			sfont := system_font_path() | ||||
| 			if g.config.font_path != '' { | ||||
| 				eprintln('font file "$g.config.font_path" does not exist, the system font ($sfont) was used instead.') | ||||
| 			} | ||||
| 
 | ||||
| 			g.ft = new_ft( | ||||
| 				font_path: sfont | ||||
| 				custom_bold_font_path: g.config.custom_bold_font_path | ||||
| 				scale: sapp.dpi_scale() | ||||
| 			) or { panic(err) } | ||||
| 			g.font_inited = true | ||||
| 		} | ||||
| 	} | ||||
| 	//
 | ||||
| 	mut pipdesc := C.sg_pipeline_desc{ | ||||
| 		label: c'alpha_image' | ||||
| 	} | ||||
| 	unsafe { C.memset(&pipdesc, 0, sizeof(pipdesc)) } | ||||
| 
 | ||||
| 	color_state := C.sg_color_state{ | ||||
| 		blend: C.sg_blend_state{ | ||||
| 			enabled: true | ||||
| 			src_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_SRC_ALPHA) | ||||
| 			dst_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA) | ||||
| 		} | ||||
| 	} | ||||
| 	pipdesc.colors[0] = color_state | ||||
| 
 | ||||
| 	g.timage_pip = sgl.make_pipeline(&pipdesc) | ||||
| 	//
 | ||||
| 	if g.config.init_fn != voidptr(0) { | ||||
| 		g.config.init_fn(g.config.user_data) | ||||
| 	} | ||||
| 	// Create images now that we can do that after sg is inited
 | ||||
| 	if g.native_rendering { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	for i in 0 .. g.image_cache.len { | ||||
| 		if g.image_cache[i].simg.id == 0 { | ||||
| 			g.image_cache[i].init_sokol_image() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn gg_frame_fn(user_data voidptr) { | ||||
| 	mut ctx := unsafe { &Context(user_data) } | ||||
| 	ctx.frame++ | ||||
|  | @ -402,38 +244,6 @@ fn gg_fail_fn(msg &char, user_data voidptr) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| //
 | ||||
| pub fn new_context(cfg Config) &Context { | ||||
| 	mut g := &Context{ | ||||
| 		width: cfg.width | ||||
| 		height: cfg.height | ||||
| 		config: cfg | ||||
| 		ft: 0 | ||||
| 		ui_mode: cfg.ui_mode | ||||
| 		native_rendering: cfg.native_rendering | ||||
| 	} | ||||
| 	g.set_bg_color(cfg.bg_color) | ||||
| 	// C.printf('new_context() %p\n', cfg.user_data)
 | ||||
| 	window := C.sapp_desc{ | ||||
| 		user_data: g | ||||
| 		init_userdata_cb: gg_init_sokol_window | ||||
| 		frame_userdata_cb: gg_frame_fn | ||||
| 		event_userdata_cb: gg_event_fn | ||||
| 		fail_userdata_cb: gg_fail_fn | ||||
| 		cleanup_userdata_cb: gg_cleanup_fn | ||||
| 		window_title: &char(cfg.window_title.str) | ||||
| 		html5_canvas_name: &char(cfg.window_title.str) | ||||
| 		width: cfg.width | ||||
| 		height: cfg.height | ||||
| 		sample_count: cfg.sample_count | ||||
| 		high_dpi: true | ||||
| 		fullscreen: cfg.fullscreen | ||||
| 		__v_native_render: cfg.native_rendering | ||||
| 	} | ||||
| 	g.window = window | ||||
| 	return g | ||||
| } | ||||
| 
 | ||||
| pub fn (gg &Context) run() { | ||||
| 	sapp.run(&gg.window) | ||||
| } | ||||
|  | @ -448,26 +258,6 @@ pub fn (mut ctx Context) set_bg_color(c gx.Color) { | |||
| 		f32(c.a) / 255.0) | ||||
| } | ||||
| 
 | ||||
| // TODO: Fix alpha
 | ||||
| pub fn (ctx &Context) draw_rect(x f32, y f32, w f32, h f32, c gx.Color) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			C.darwin_draw_rect(x, ctx.height - (y + h), w, h, c) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if c.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	sgl.c4b(c.r, c.g, c.b, c.a) | ||||
| 	sgl.begin_quads() | ||||
| 	sgl.v2f(x * ctx.scale, y * ctx.scale) | ||||
| 	sgl.v2f((x + w) * ctx.scale, y * ctx.scale) | ||||
| 	sgl.v2f((x + w) * ctx.scale, (y + h) * ctx.scale) | ||||
| 	sgl.v2f(x * ctx.scale, (y + h) * ctx.scale) | ||||
| 	sgl.end() | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| pub fn (ctx &Context) draw_square(x f32, y f32, s f32, c gx.Color) { | ||||
| 	ctx.draw_rect(x, y, s, s, c) | ||||
|  | @ -509,33 +299,6 @@ pub fn (ctx &Context) draw_empty_square(x f32, y f32, s f32, c gx.Color) { | |||
| 	ctx.draw_empty_rect(x, y, s, s, c) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_circle_line(x f32, y f32, r int, segments int, c gx.Color) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			C.darwin_draw_circle(x - r + 1, ctx.height - (y + r + 3), r, c) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if c.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	sgl.c4b(c.r, c.g, c.b, c.a) | ||||
| 	nx := x * ctx.scale | ||||
| 	ny := y * ctx.scale | ||||
| 	nr := r * ctx.scale | ||||
| 	mut theta := f32(0) | ||||
| 	mut xx := f32(0) | ||||
| 	mut yy := f32(0) | ||||
| 	sgl.begin_line_strip() | ||||
| 	for i := 0; i < segments + 1; i++ { | ||||
| 		theta = 2.0 * f32(math.pi) * f32(i) / f32(segments) | ||||
| 		xx = nr * math.cosf(theta) | ||||
| 		yy = nr * math.sinf(theta) | ||||
| 		sgl.v2f(xx + nx, yy + ny) | ||||
| 	} | ||||
| 	sgl.end() | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_circle(x f32, y f32, r f32, c gx.Color) { | ||||
| 	ctx.draw_circle_with_segments(x, y, r, 10, c) | ||||
| } | ||||
|  | @ -890,14 +653,6 @@ pub fn (ctx &Context) draw_empty_poly(points []f32, c gx.Color) { | |||
| 	sgl.end() | ||||
| } | ||||
| 
 | ||||
| pub fn screen_size() Size { | ||||
| 	$if macos { | ||||
| 		return C.gg_get_screen_size() | ||||
| 	} | ||||
| 	// TODO windows, linux, etc
 | ||||
| 	return Size{} | ||||
| } | ||||
| 
 | ||||
| // window_size returns the `Size` of the active window
 | ||||
| pub fn window_size() Size { | ||||
| 	s := dpi_scale() | ||||
|  | @ -921,26 +676,3 @@ pub fn dpi_scale() f32 { | |||
| 	} | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| pub fn high_dpi() bool { | ||||
| 	return C.sapp_high_dpi() | ||||
| } | ||||
| 
 | ||||
| fn C.WaitMessage() | ||||
| 
 | ||||
| /* | ||||
| pub fn wait_events() { | ||||
| 	unsafe { | ||||
| 		$if macos { | ||||
| 			#NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny | ||||
| 			#untilDate:[NSDate distantFuture] | ||||
| 			#inMode:NSDefaultRunLoopMode | ||||
| 			#dequeue:YES]; | ||||
| 			#[NSApp sendEvent:event]; | ||||
| 		} | ||||
| 		$if windows { | ||||
| 			C.WaitMessage() | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| */ | ||||
|  |  | |||
|  | @ -0,0 +1,169 @@ | |||
| // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
 | ||||
| // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
 | ||||
| module gg | ||||
| 
 | ||||
| import os | ||||
| import stbi | ||||
| import sokol.gfx | ||||
| 
 | ||||
| fn C.sg_isvalid() bool | ||||
| 
 | ||||
| // TODO return ?Image
 | ||||
| pub fn (mut ctx Context) create_image(file string) Image { | ||||
| 	// println('\ncreate_image("$file")')
 | ||||
| 	if !os.exists(file) { | ||||
| 		return Image{} | ||||
| 	} | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			// return C.darwin_create_image(file)
 | ||||
| 			mut img := C.darwin_create_image(file) | ||||
| 			// println('created macos image: $img.path w=$img.width')
 | ||||
| 			// C.printf('p = %p\n', img.data)
 | ||||
| 			img.id = ctx.image_cache.len | ||||
| 			ctx.image_cache << img | ||||
| 			return img | ||||
| 		} | ||||
| 	} | ||||
| 	if !C.sg_isvalid() { | ||||
| 		// Sokol is not initialized yet, add stbi object to a queue/cache
 | ||||
| 		// ctx.image_queue << file
 | ||||
| 		stb_img := stbi.load(file) or { return Image{} } | ||||
| 		img := Image{ | ||||
| 			width: stb_img.width | ||||
| 			height: stb_img.height | ||||
| 			nr_channels: stb_img.nr_channels | ||||
| 			ok: false | ||||
| 			data: stb_img.data | ||||
| 			ext: stb_img.ext | ||||
| 			path: file | ||||
| 			id: ctx.image_cache.len | ||||
| 		} | ||||
| 		ctx.image_cache << img | ||||
| 		return img | ||||
| 	} | ||||
| 	mut img := create_image(file) | ||||
| 	img.id = ctx.image_cache.len | ||||
| 	ctx.image_cache << img | ||||
| 	return img | ||||
| } | ||||
| 
 | ||||
| pub fn (mut img Image) init_sokol_image() &Image { | ||||
| 	// println('\n init sokol image $img.path ok=$img.simg_ok')
 | ||||
| 	mut img_desc := C.sg_image_desc{ | ||||
| 		width: img.width | ||||
| 		height: img.height | ||||
| 		num_mipmaps: 0 | ||||
| 		wrap_u: .clamp_to_edge | ||||
| 		wrap_v: .clamp_to_edge | ||||
| 		label: img.path.str | ||||
| 		d3d11_texture: 0 | ||||
| 	} | ||||
| 	img_desc.data.subimage[0][0] = C.sg_range{ | ||||
| 		ptr: img.data | ||||
| 		size: size_t(img.nr_channels * img.width * img.height) | ||||
| 	} | ||||
| 	img.simg = C.sg_make_image(&img_desc) | ||||
| 	img.simg_ok = true | ||||
| 	img.ok = true | ||||
| 	return img | ||||
| } | ||||
| 
 | ||||
| // draw_image draws the provided image onto the screen
 | ||||
| pub fn (ctx &Context) draw_image(x f32, y f32, width f32, height f32, img_ &Image) { | ||||
| 	$if macos { | ||||
| 		if img_.id >= ctx.image_cache.len { | ||||
| 			eprintln('gg: draw_image() bad img id $img_.id (img cache len = $ctx.image_cache.len)') | ||||
| 			return | ||||
| 		} | ||||
| 		if ctx.native_rendering { | ||||
| 			if img_.width == 0 { | ||||
| 				return | ||||
| 			} | ||||
| 			if !os.exists(img_.path) { | ||||
| 				return | ||||
| 			} | ||||
| 			C.darwin_draw_image(x, ctx.height - (y + height), width, height, img_) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.draw_image_with_config( | ||||
| 		img: img_ | ||||
| 		img_rect: Rect{x, y, width, height} | ||||
| 		part_rect: Rect{0, 0, img_.width, img_.height} | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // new_streaming_image returns a cached `image_idx` of a special image, that
 | ||||
| // can be updated *each frame* by calling:  gg.update_pixel_data(image_idx, buf)
 | ||||
| // ... where buf is a pointer to the actual pixel data for the image.
 | ||||
| // NB: you still need to call app.gg.draw_image after that, to actually draw it.
 | ||||
| pub fn (mut ctx Context) new_streaming_image(w int, h int, channels int, sicfg StreamingImageConfig) int { | ||||
| 	mut img := Image{} | ||||
| 	img.width = w | ||||
| 	img.height = h | ||||
| 	img.nr_channels = channels // 4 bytes per pixel for .rgba8, see pixel_format
 | ||||
| 	mut img_desc := C.sg_image_desc{ | ||||
| 		width: img.width | ||||
| 		height: img.height | ||||
| 		pixel_format: sicfg.pixel_format | ||||
| 		num_slices: 1 | ||||
| 		num_mipmaps: 1 | ||||
| 		usage: .stream | ||||
| 		wrap_u: sicfg.wrap_u | ||||
| 		wrap_v: sicfg.wrap_v | ||||
| 		min_filter: sicfg.min_filter | ||||
| 		mag_filter: sicfg.mag_filter | ||||
| 		label: img.path.str | ||||
| 	} | ||||
| 	// Sokol requires that streamed images have NO .ptr/.size initially:
 | ||||
| 	img_desc.data.subimage[0][0] = C.sg_range{ | ||||
| 		ptr: 0 | ||||
| 		size: size_t(0) | ||||
| 	} | ||||
| 	img.simg = C.sg_make_image(&img_desc) | ||||
| 	img.simg_ok = true | ||||
| 	img.ok = true | ||||
| 	img_idx := ctx.cache_image(img) | ||||
| 	return img_idx | ||||
| } | ||||
| 
 | ||||
| // update_pixel_data is a helper for working with image streams (i.e. images,
 | ||||
| // that are updated dynamically by the CPU on each frame)
 | ||||
| pub fn (mut ctx Context) update_pixel_data(cached_image_idx int, buf &byte) { | ||||
| 	mut image := ctx.get_cached_image_by_idx(cached_image_idx) | ||||
| 	image.update_pixel_data(buf) | ||||
| } | ||||
| 
 | ||||
| pub fn (mut img Image) update_pixel_data(buf &byte) { | ||||
| 	mut data := C.sg_image_data{} | ||||
| 	data.subimage[0][0].ptr = buf | ||||
| 	data.subimage[0][0].size = size_t(img.width * img.height * img.nr_channels) | ||||
| 	gfx.update_image(img.simg, &data) | ||||
| } | ||||
| 
 | ||||
| // TODO copypasta
 | ||||
| pub fn (mut ctx Context) create_image_with_size(file string, width int, height int) Image { | ||||
| 	if !C.sg_isvalid() { | ||||
| 		// Sokol is not initialized yet, add stbi object to a queue/cache
 | ||||
| 		// ctx.image_queue << file
 | ||||
| 		stb_img := stbi.load(file) or { return Image{} } | ||||
| 		img := Image{ | ||||
| 			width: width | ||||
| 			height: height | ||||
| 			nr_channels: stb_img.nr_channels | ||||
| 			ok: false | ||||
| 			data: stb_img.data | ||||
| 			ext: stb_img.ext | ||||
| 			path: file | ||||
| 			id: ctx.image_cache.len | ||||
| 		} | ||||
| 		ctx.image_cache << img | ||||
| 		return img | ||||
| 	} | ||||
| 	mut img := create_image(file) | ||||
| 	img.id = ctx.image_cache.len | ||||
| 	ctx.image_cache << img | ||||
| 	return img | ||||
| } | ||||
							
								
								
									
										162
									
								
								vlib/gg/image.v
								
								
								
								
							
							
						
						
									
										162
									
								
								vlib/gg/image.v
								
								
								
								
							|  | @ -48,73 +48,6 @@ pub: | |||
| 	height f32 | ||||
| } | ||||
| 
 | ||||
| fn C.sg_isvalid() bool | ||||
| 
 | ||||
| // TODO return ?Image
 | ||||
| pub fn (mut ctx Context) create_image(file string) Image { | ||||
| 	// println('\ncreate_image("$file")')
 | ||||
| 	if !os.exists(file) { | ||||
| 		return Image{} | ||||
| 	} | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			// return C.darwin_create_image(file)
 | ||||
| 			mut img := C.darwin_create_image(file) | ||||
| 			// println('created macos image: $img.path w=$img.width')
 | ||||
| 			// C.printf('p = %p\n', img.data)
 | ||||
| 			img.id = ctx.image_cache.len | ||||
| 			ctx.image_cache << img | ||||
| 			return img | ||||
| 		} | ||||
| 	} | ||||
| 	if !C.sg_isvalid() { | ||||
| 		// Sokol is not initialized yet, add stbi object to a queue/cache
 | ||||
| 		// ctx.image_queue << file
 | ||||
| 		stb_img := stbi.load(file) or { return Image{} } | ||||
| 		img := Image{ | ||||
| 			width: stb_img.width | ||||
| 			height: stb_img.height | ||||
| 			nr_channels: stb_img.nr_channels | ||||
| 			ok: false | ||||
| 			data: stb_img.data | ||||
| 			ext: stb_img.ext | ||||
| 			path: file | ||||
| 			id: ctx.image_cache.len | ||||
| 		} | ||||
| 		ctx.image_cache << img | ||||
| 		return img | ||||
| 	} | ||||
| 	mut img := create_image(file) | ||||
| 	img.id = ctx.image_cache.len | ||||
| 	ctx.image_cache << img | ||||
| 	return img | ||||
| } | ||||
| 
 | ||||
| // TODO copypasta
 | ||||
| pub fn (mut ctx Context) create_image_with_size(file string, width int, height int) Image { | ||||
| 	if !C.sg_isvalid() { | ||||
| 		// Sokol is not initialized yet, add stbi object to a queue/cache
 | ||||
| 		// ctx.image_queue << file
 | ||||
| 		stb_img := stbi.load(file) or { return Image{} } | ||||
| 		img := Image{ | ||||
| 			width: width | ||||
| 			height: height | ||||
| 			nr_channels: stb_img.nr_channels | ||||
| 			ok: false | ||||
| 			data: stb_img.data | ||||
| 			ext: stb_img.ext | ||||
| 			path: file | ||||
| 			id: ctx.image_cache.len | ||||
| 		} | ||||
| 		ctx.image_cache << img | ||||
| 		return img | ||||
| 	} | ||||
| 	mut img := create_image(file) | ||||
| 	img.id = ctx.image_cache.len | ||||
| 	ctx.image_cache << img | ||||
| 	return img | ||||
| } | ||||
| 
 | ||||
| // TODO remove this
 | ||||
| fn create_image(file string) Image { | ||||
| 	if !os.exists(file) { | ||||
|  | @ -165,27 +98,6 @@ pub fn (mut ctx Context) get_cached_image_by_idx(image_idx int) &Image { | |||
| 	return &ctx.image_cache[image_idx] | ||||
| } | ||||
| 
 | ||||
| pub fn (mut img Image) init_sokol_image() &Image { | ||||
| 	// println('\n init sokol image $img.path ok=$img.simg_ok')
 | ||||
| 	mut img_desc := C.sg_image_desc{ | ||||
| 		width: img.width | ||||
| 		height: img.height | ||||
| 		num_mipmaps: 0 | ||||
| 		wrap_u: .clamp_to_edge | ||||
| 		wrap_v: .clamp_to_edge | ||||
| 		label: img.path.str | ||||
| 		d3d11_texture: 0 | ||||
| 	} | ||||
| 	img_desc.data.subimage[0][0] = C.sg_range{ | ||||
| 		ptr: img.data | ||||
| 		size: size_t(img.nr_channels * img.width * img.height) | ||||
| 	} | ||||
| 	img.simg = C.sg_make_image(&img_desc) | ||||
| 	img.simg_ok = true | ||||
| 	img.ok = true | ||||
| 	return img | ||||
| } | ||||
| 
 | ||||
| pub struct StreamingImageConfig { | ||||
| 	pixel_format gfx.PixelFormat = .rgba8 | ||||
| 	wrap_u       gfx.Wrap        = .clamp_to_edge | ||||
|  | @ -196,54 +108,6 @@ pub struct StreamingImageConfig { | |||
| 	num_slices   int = 1 | ||||
| } | ||||
| 
 | ||||
| // new_streaming_image returns a cached `image_idx` of a special image, that
 | ||||
| // can be updated *each frame* by calling:  gg.update_pixel_data(image_idx, buf)
 | ||||
| // ... where buf is a pointer to the actual pixel data for the image.
 | ||||
| // NB: you still need to call app.gg.draw_image after that, to actually draw it.
 | ||||
| pub fn (mut ctx Context) new_streaming_image(w int, h int, channels int, sicfg StreamingImageConfig) int { | ||||
| 	mut img := Image{} | ||||
| 	img.width = w | ||||
| 	img.height = h | ||||
| 	img.nr_channels = channels // 4 bytes per pixel for .rgba8, see pixel_format
 | ||||
| 	mut img_desc := C.sg_image_desc{ | ||||
| 		width: img.width | ||||
| 		height: img.height | ||||
| 		pixel_format: sicfg.pixel_format | ||||
| 		num_slices: 1 | ||||
| 		num_mipmaps: 1 | ||||
| 		usage: .stream | ||||
| 		wrap_u: sicfg.wrap_u | ||||
| 		wrap_v: sicfg.wrap_v | ||||
| 		min_filter: sicfg.min_filter | ||||
| 		mag_filter: sicfg.mag_filter | ||||
| 		label: img.path.str | ||||
| 	} | ||||
| 	// Sokol requires that streamed images have NO .ptr/.size initially:
 | ||||
| 	img_desc.data.subimage[0][0] = C.sg_range{ | ||||
| 		ptr: 0 | ||||
| 		size: size_t(0) | ||||
| 	} | ||||
| 	img.simg = C.sg_make_image(&img_desc) | ||||
| 	img.simg_ok = true | ||||
| 	img.ok = true | ||||
| 	img_idx := ctx.cache_image(img) | ||||
| 	return img_idx | ||||
| } | ||||
| 
 | ||||
| // update_pixel_data is a helper for working with image streams (i.e. images,
 | ||||
| // that are updated dynamically by the CPU on each frame)
 | ||||
| pub fn (mut ctx Context) update_pixel_data(cached_image_idx int, buf &byte) { | ||||
| 	mut image := ctx.get_cached_image_by_idx(cached_image_idx) | ||||
| 	image.update_pixel_data(buf) | ||||
| } | ||||
| 
 | ||||
| pub fn (mut img Image) update_pixel_data(buf &byte) { | ||||
| 	mut data := C.sg_image_data{} | ||||
| 	data.subimage[0][0].ptr = buf | ||||
| 	data.subimage[0][0].size = size_t(img.width * img.height * img.nr_channels) | ||||
| 	gfx.update_image(img.simg, &data) | ||||
| } | ||||
| 
 | ||||
| // draw_image_with_config takes in a config that details how the
 | ||||
| // provided image should be drawn onto the screen
 | ||||
| pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) { | ||||
|  | @ -332,32 +196,6 @@ pub fn (ctx &Context) draw_image_part(img_rect Rect, part_rect Rect, img_ &Image | |||
| 	) | ||||
| } | ||||
| 
 | ||||
| // draw_image draws the provided image onto the screen
 | ||||
| pub fn (ctx &Context) draw_image(x f32, y f32, width f32, height f32, img_ &Image) { | ||||
| 	$if macos { | ||||
| 		if img_.id >= ctx.image_cache.len { | ||||
| 			eprintln('gg: draw_image() bad img id $img_.id (img cache len = $ctx.image_cache.len)') | ||||
| 			return | ||||
| 		} | ||||
| 		if ctx.native_rendering { | ||||
| 			if img_.width == 0 { | ||||
| 				return | ||||
| 			} | ||||
| 			if !os.exists(img_.path) { | ||||
| 				return | ||||
| 			} | ||||
| 			C.darwin_draw_image(x, ctx.height - (y + height), width, height, img_) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.draw_image_with_config( | ||||
| 		img: img_ | ||||
| 		img_rect: Rect{x, y, width, height} | ||||
| 		part_rect: Rect{0, 0, img_.width, img_.height} | ||||
| 	) | ||||
| } | ||||
| 
 | ||||
| // draw_image_flipped draws the provided image flipped horizontally (use `draw_image_with_config` to flip vertically)
 | ||||
| pub fn (ctx &Context) draw_image_flipped(x f32, y f32, width f32, height f32, img_ &Image) { | ||||
| 	ctx.draw_image_with_config( | ||||
|  |  | |||
|  | @ -0,0 +1,226 @@ | |||
| // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
 | ||||
| // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
 | ||||
| module gg | ||||
| 
 | ||||
| import sokol.sfons | ||||
| import sokol.sgl | ||||
| import gx | ||||
| import os | ||||
| 
 | ||||
| struct FT { | ||||
| pub: | ||||
| 	fons        &C.FONScontext | ||||
| 	font_normal int | ||||
| 	font_bold   int | ||||
| 	font_mono   int | ||||
| 	font_italic int | ||||
| 	scale       f32 = 1.0 | ||||
| } | ||||
| 
 | ||||
| fn new_ft(c FTConfig) ?&FT { | ||||
| 	if c.font_path == '' { | ||||
| 		if c.bytes_normal.len > 0 { | ||||
| 			fons := sfons.create(512, 512, 1) | ||||
| 			bytes_normal := c.bytes_normal | ||||
| 			bytes_bold := if c.bytes_bold.len > 0 { | ||||
| 				c.bytes_bold | ||||
| 			} else { | ||||
| 				debug_font_println('setting bold variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 			bytes_mono := if c.bytes_mono.len > 0 { | ||||
| 				c.bytes_mono | ||||
| 			} else { | ||||
| 				debug_font_println('setting mono variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 			bytes_italic := if c.bytes_italic.len > 0 { | ||||
| 				c.bytes_italic | ||||
| 			} else { | ||||
| 				debug_font_println('setting italic variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 
 | ||||
| 			return &FT{ | ||||
| 				fons: fons | ||||
| 				font_normal: C.fonsAddFontMem(fons, c'sans', bytes_normal.data, bytes_normal.len, | ||||
| 					false) | ||||
| 				font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, | ||||
| 					false) | ||||
| 				font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, | ||||
| 					false) | ||||
| 				font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, | ||||
| 					false) | ||||
| 				scale: c.scale | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Load default font
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if c.font_path == '' || !os.exists(c.font_path) { | ||||
| 		$if !android { | ||||
| 			println('failed to load font "$c.font_path"') | ||||
| 			return none | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	mut bytes := []byte{} | ||||
| 	$if android { | ||||
| 		// First try any filesystem paths
 | ||||
| 		bytes = os.read_bytes(c.font_path) or { []byte{} } | ||||
| 		if bytes.len == 0 { | ||||
| 			// ... then try the APK asset path
 | ||||
| 			bytes = os.read_apk_asset(c.font_path) or { | ||||
| 				println('failed to load font "$c.font_path"') | ||||
| 				return none | ||||
| 			} | ||||
| 		} | ||||
| 	} $else { | ||||
| 		bytes = os.read_bytes(c.font_path) or { | ||||
| 			println('failed to load font "$c.font_path"') | ||||
| 			return none | ||||
| 		} | ||||
| 	} | ||||
| 	bold_path := if c.custom_bold_font_path != '' { | ||||
| 		c.custom_bold_font_path | ||||
| 	} else { | ||||
| 		get_font_path_variant(c.font_path, .bold) | ||||
| 	} | ||||
| 	bytes_bold := os.read_bytes(bold_path) or { | ||||
| 		debug_font_println('failed to load font "$bold_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	mono_path := get_font_path_variant(c.font_path, .mono) | ||||
| 	bytes_mono := os.read_bytes(mono_path) or { | ||||
| 		debug_font_println('failed to load font "$mono_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	italic_path := get_font_path_variant(c.font_path, .italic) | ||||
| 	bytes_italic := os.read_bytes(italic_path) or { | ||||
| 		debug_font_println('failed to load font "$italic_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	fons := sfons.create(512, 512, 1) | ||||
| 	return &FT{ | ||||
| 		fons: fons | ||||
| 		font_normal: C.fonsAddFontMem(fons, c'sans', bytes.data, bytes.len, false) | ||||
| 		font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, false) | ||||
| 		font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, false) | ||||
| 		font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, | ||||
| 			false) | ||||
| 		scale: c.scale | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) set_cfg(cfg gx.TextCfg) { | ||||
| 	if !ctx.font_inited { | ||||
| 		return | ||||
| 	} | ||||
| 	if cfg.bold { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_bold) | ||||
| 	} else if cfg.mono { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_mono) | ||||
| 	} else if cfg.italic { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_italic) | ||||
| 	} else { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_normal) | ||||
| 	} | ||||
| 	scale := if ctx.ft.scale == 0 { f32(1) } else { ctx.ft.scale } | ||||
| 	size := if cfg.mono { cfg.size - 2 } else { cfg.size } | ||||
| 	ctx.ft.fons.set_size(scale * f32(size)) | ||||
| 	C.fonsSetAlign(ctx.ft.fons, int(cfg.align) | int(cfg.vertical_align)) | ||||
| 	color := C.sfons_rgba(cfg.color.r, cfg.color.g, cfg.color.b, cfg.color.a) | ||||
| 	if cfg.color.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	C.fonsSetColor(ctx.ft.fons, color) | ||||
| 	ascender := f32(0.0) | ||||
| 	descender := f32(0.0) | ||||
| 	lh := f32(0.0) | ||||
| 	ctx.ft.fons.vert_metrics(&ascender, &descender, &lh) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_text(x int, y int, text_ string, cfg gx.TextCfg) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			if cfg.align == gx.align_right { | ||||
| 				width := ctx.text_width(text_) | ||||
| 				C.darwin_draw_string(x - width, ctx.height - y, text_, cfg) | ||||
| 			} else { | ||||
| 				C.darwin_draw_string(x, ctx.height - y, text_, cfg) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if !ctx.font_inited { | ||||
| 		eprintln('gg: draw_text(): font not initialized') | ||||
| 		return | ||||
| 	} | ||||
| 	// text := text_.trim_space() // TODO remove/optimize
 | ||||
| 	// mut text := text_
 | ||||
| 	// if text.contains('\t') {
 | ||||
| 	// text = text.replace('\t', '    ')
 | ||||
| 	// }
 | ||||
| 	ctx.set_cfg(cfg) | ||||
| 	scale := if ctx.ft.scale == 0 { f32(1) } else { ctx.ft.scale } | ||||
| 	C.fonsDrawText(ctx.ft.fons, x * scale, y * scale, &char(text_.str), 0) // TODO: check offsets/alignment
 | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_text_def(x int, y int, text string) { | ||||
| 	ctx.draw_text(x, y, text) | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn (mut gg FT) init_font() { | ||||
| } | ||||
| */ | ||||
| pub fn (ft &FT) flush() { | ||||
| 	sfons.flush(ft.fons) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_width(s string) int { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			return C.darwin_text_width(s) | ||||
| 		} | ||||
| 	} | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	if s.ends_with(' ') { | ||||
| 		return int((buf[2] - buf[0]) / ctx.scale) + | ||||
| 			ctx.text_width('i') // TODO fix this in fontstash?
 | ||||
| 	} | ||||
| 	res := int((buf[2] - buf[0]) / ctx.scale) | ||||
| 	// println('TW "$s" = $res')
 | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			return res * 2 | ||||
| 		} | ||||
| 	} | ||||
| 	return int((buf[2] - buf[0]) / ctx.scale) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_height(s string) int { | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	return int((buf[3] - buf[1]) / ctx.scale) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_size(s string) (int, int) { | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0, 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	return int((buf[2] - buf[0]) / ctx.scale), int((buf[3] - buf[1]) / ctx.scale) | ||||
| } | ||||
|  | @ -2,10 +2,8 @@ | |||
| // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
 | ||||
| module gg | ||||
| 
 | ||||
| import sokol.sfons | ||||
| import sokol.sgl | ||||
| import gx | ||||
| import os | ||||
| import gx | ||||
| 
 | ||||
| enum FontVariant { | ||||
| 	normal = 0 | ||||
|  | @ -14,16 +12,6 @@ enum FontVariant { | |||
| 	italic | ||||
| } | ||||
| 
 | ||||
| struct FT { | ||||
| pub: | ||||
| 	fons        &C.FONScontext | ||||
| 	font_normal int | ||||
| 	font_bold   int | ||||
| 	font_mono   int | ||||
| 	font_italic int | ||||
| 	scale       f32 = 1.0 | ||||
| } | ||||
| 
 | ||||
| struct FTConfig { | ||||
| 	font_path             string | ||||
| 	custom_bold_font_path string | ||||
|  | @ -42,214 +30,6 @@ struct StringToRender { | |||
| 	cfg  gx.TextCfg | ||||
| } | ||||
| 
 | ||||
| fn new_ft(c FTConfig) ?&FT { | ||||
| 	if c.font_path == '' { | ||||
| 		if c.bytes_normal.len > 0 { | ||||
| 			fons := sfons.create(512, 512, 1) | ||||
| 			bytes_normal := c.bytes_normal | ||||
| 			bytes_bold := if c.bytes_bold.len > 0 { | ||||
| 				c.bytes_bold | ||||
| 			} else { | ||||
| 				debug_font_println('setting bold variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 			bytes_mono := if c.bytes_mono.len > 0 { | ||||
| 				c.bytes_mono | ||||
| 			} else { | ||||
| 				debug_font_println('setting mono variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 			bytes_italic := if c.bytes_italic.len > 0 { | ||||
| 				c.bytes_italic | ||||
| 			} else { | ||||
| 				debug_font_println('setting italic variant to normal') | ||||
| 				bytes_normal | ||||
| 			} | ||||
| 
 | ||||
| 			return &FT{ | ||||
| 				fons: fons | ||||
| 				font_normal: C.fonsAddFontMem(fons, c'sans', bytes_normal.data, bytes_normal.len, | ||||
| 					false) | ||||
| 				font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, | ||||
| 					false) | ||||
| 				font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, | ||||
| 					false) | ||||
| 				font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, | ||||
| 					false) | ||||
| 				scale: c.scale | ||||
| 			} | ||||
| 		} else { | ||||
| 			// Load default font
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if c.font_path == '' || !os.exists(c.font_path) { | ||||
| 		$if !android { | ||||
| 			println('failed to load font "$c.font_path"') | ||||
| 			return none | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	mut bytes := []byte{} | ||||
| 	$if android { | ||||
| 		// First try any filesystem paths
 | ||||
| 		bytes = os.read_bytes(c.font_path) or { []byte{} } | ||||
| 		if bytes.len == 0 { | ||||
| 			// ... then try the APK asset path
 | ||||
| 			bytes = os.read_apk_asset(c.font_path) or { | ||||
| 				println('failed to load font "$c.font_path"') | ||||
| 				return none | ||||
| 			} | ||||
| 		} | ||||
| 	} $else { | ||||
| 		bytes = os.read_bytes(c.font_path) or { | ||||
| 			println('failed to load font "$c.font_path"') | ||||
| 			return none | ||||
| 		} | ||||
| 	} | ||||
| 	bold_path := if c.custom_bold_font_path != '' { | ||||
| 		c.custom_bold_font_path | ||||
| 	} else { | ||||
| 		get_font_path_variant(c.font_path, .bold) | ||||
| 	} | ||||
| 	bytes_bold := os.read_bytes(bold_path) or { | ||||
| 		debug_font_println('failed to load font "$bold_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	mono_path := get_font_path_variant(c.font_path, .mono) | ||||
| 	bytes_mono := os.read_bytes(mono_path) or { | ||||
| 		debug_font_println('failed to load font "$mono_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	italic_path := get_font_path_variant(c.font_path, .italic) | ||||
| 	bytes_italic := os.read_bytes(italic_path) or { | ||||
| 		debug_font_println('failed to load font "$italic_path"') | ||||
| 		bytes | ||||
| 	} | ||||
| 	fons := sfons.create(512, 512, 1) | ||||
| 	return &FT{ | ||||
| 		fons: fons | ||||
| 		font_normal: C.fonsAddFontMem(fons, c'sans', bytes.data, bytes.len, false) | ||||
| 		font_bold: C.fonsAddFontMem(fons, c'sans', bytes_bold.data, bytes_bold.len, false) | ||||
| 		font_mono: C.fonsAddFontMem(fons, c'sans', bytes_mono.data, bytes_mono.len, false) | ||||
| 		font_italic: C.fonsAddFontMem(fons, c'sans', bytes_italic.data, bytes_italic.len, | ||||
| 			false) | ||||
| 		scale: c.scale | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) set_cfg(cfg gx.TextCfg) { | ||||
| 	if !ctx.font_inited { | ||||
| 		return | ||||
| 	} | ||||
| 	if cfg.bold { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_bold) | ||||
| 	} else if cfg.mono { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_mono) | ||||
| 	} else if cfg.italic { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_italic) | ||||
| 	} else { | ||||
| 		ctx.ft.fons.set_font(ctx.ft.font_normal) | ||||
| 	} | ||||
| 	scale := if ctx.ft.scale == 0 { f32(1) } else { ctx.ft.scale } | ||||
| 	size := if cfg.mono { cfg.size - 2 } else { cfg.size } | ||||
| 	ctx.ft.fons.set_size(scale * f32(size)) | ||||
| 	C.fonsSetAlign(ctx.ft.fons, int(cfg.align) | int(cfg.vertical_align)) | ||||
| 	color := C.sfons_rgba(cfg.color.r, cfg.color.g, cfg.color.b, cfg.color.a) | ||||
| 	if cfg.color.a != 255 { | ||||
| 		sgl.load_pipeline(ctx.timage_pip) | ||||
| 	} | ||||
| 	C.fonsSetColor(ctx.ft.fons, color) | ||||
| 	ascender := f32(0.0) | ||||
| 	descender := f32(0.0) | ||||
| 	lh := f32(0.0) | ||||
| 	ctx.ft.fons.vert_metrics(&ascender, &descender, &lh) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_text(x int, y int, text_ string, cfg gx.TextCfg) { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			if cfg.align == gx.align_right { | ||||
| 				width := ctx.text_width(text_) | ||||
| 				C.darwin_draw_string(x - width, ctx.height - y, text_, cfg) | ||||
| 			} else { | ||||
| 				C.darwin_draw_string(x, ctx.height - y, text_, cfg) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	if !ctx.font_inited { | ||||
| 		eprintln('gg: draw_text(): font not initialized') | ||||
| 		return | ||||
| 	} | ||||
| 	// text := text_.trim_space() // TODO remove/optimize
 | ||||
| 	// mut text := text_
 | ||||
| 	// if text.contains('\t') {
 | ||||
| 	// text = text.replace('\t', '    ')
 | ||||
| 	// }
 | ||||
| 	ctx.set_cfg(cfg) | ||||
| 	scale := if ctx.ft.scale == 0 { f32(1) } else { ctx.ft.scale } | ||||
| 	C.fonsDrawText(ctx.ft.fons, x * scale, y * scale, &char(text_.str), 0) // TODO: check offsets/alignment
 | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) draw_text_def(x int, y int, text string) { | ||||
| 	ctx.draw_text(x, y, text) | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| pub fn (mut gg FT) init_font() { | ||||
| } | ||||
| */ | ||||
| pub fn (ft &FT) flush() { | ||||
| 	sfons.flush(ft.fons) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_width(s string) int { | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			return C.darwin_text_width(s) | ||||
| 		} | ||||
| 	} | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	if s.ends_with(' ') { | ||||
| 		return int((buf[2] - buf[0]) / ctx.scale) + | ||||
| 			ctx.text_width('i') // TODO fix this in fontstash?
 | ||||
| 	} | ||||
| 	res := int((buf[2] - buf[0]) / ctx.scale) | ||||
| 	// println('TW "$s" = $res')
 | ||||
| 	$if macos { | ||||
| 		if ctx.native_rendering { | ||||
| 			return res * 2 | ||||
| 		} | ||||
| 	} | ||||
| 	return int((buf[2] - buf[0]) / ctx.scale) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_height(s string) int { | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	return int((buf[3] - buf[1]) / ctx.scale) | ||||
| } | ||||
| 
 | ||||
| pub fn (ctx &Context) text_size(s string) (int, int) { | ||||
| 	// ctx.set_cfg(cfg) TODO
 | ||||
| 	if !ctx.font_inited { | ||||
| 		return 0, 0 | ||||
| 	} | ||||
| 	mut buf := [4]f32{} | ||||
| 	C.fonsTextBounds(ctx.ft.fons, 0, 0, &char(s.str), 0, &buf[0]) | ||||
| 	return int((buf[2] - buf[0]) / ctx.scale), int((buf[3] - buf[1]) / ctx.scale) | ||||
| } | ||||
| 
 | ||||
| pub fn system_font_path() string { | ||||
| 	env_font := os.getenv('VUI_FONT') | ||||
| 	if env_font != '' && os.exists(env_font) { | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| module gx | ||||
| 
 | ||||
| import fontstash | ||||
| 
 | ||||
| const used_import = fontstash.used_import | ||||
| 
 | ||||
| pub enum HorizontalAlign { | ||||
| 	left = C.FONS_ALIGN_LEFT | ||||
| 	center = C.FONS_ALIGN_CENTER | ||||
| 	right = C.FONS_ALIGN_RIGHT | ||||
| } | ||||
| 
 | ||||
| pub enum VerticalAlign { | ||||
| 	top = C.FONS_ALIGN_TOP | ||||
| 	middle = C.FONS_ALIGN_MIDDLE | ||||
| 	bottom = C.FONS_ALIGN_BOTTOM | ||||
| 	baseline = C.FONS_ALIGN_BASELINE | ||||
| } | ||||
|  | @ -1,30 +1,11 @@ | |||
| module gx | ||||
| 
 | ||||
| import fontstash | ||||
| 
 | ||||
| const ( | ||||
| 	used_import = fontstash.used_import | ||||
| ) | ||||
| 
 | ||||
| // TODO: remove these and uae the enum everywhere
 | ||||
| pub const ( | ||||
| 	align_left  = HorizontalAlign.left | ||||
| 	align_right = HorizontalAlign.right | ||||
| ) | ||||
| 
 | ||||
| pub enum HorizontalAlign { | ||||
| 	left = C.FONS_ALIGN_LEFT | ||||
| 	center = C.FONS_ALIGN_CENTER | ||||
| 	right = C.FONS_ALIGN_RIGHT | ||||
| } | ||||
| 
 | ||||
| pub enum VerticalAlign { | ||||
| 	top = C.FONS_ALIGN_TOP | ||||
| 	middle = C.FONS_ALIGN_MIDDLE | ||||
| 	bottom = C.FONS_ALIGN_BOTTOM | ||||
| 	baseline = C.FONS_ALIGN_BASELINE | ||||
| } | ||||
| 
 | ||||
| pub struct TextCfg { | ||||
| pub: | ||||
| 	color          Color = black | ||||
|  |  | |||
|  | @ -2,9 +2,7 @@ module sapp | |||
| 
 | ||||
| import sokol.gfx | ||||
| 
 | ||||
| pub const ( | ||||
| 	used_import = gfx.used_import | ||||
| ) | ||||
| pub const used_import = gfx.used_import | ||||
| 
 | ||||
| // Android needs a global reference to `g_desc`
 | ||||
| __global ( | ||||
|  | @ -2,10 +2,8 @@ module sfons | |||
| 
 | ||||
| import fontstash | ||||
| 
 | ||||
| const ( | ||||
| // keep v from warning about unused imports
 | ||||
| 	used_import = fontstash.used_import + 1 | ||||
| ) | ||||
| const used_import = fontstash.used_import + 1 | ||||
| 
 | ||||
| [inline] | ||||
| pub fn create(width int, height int, flags int) &C.FONScontext { | ||||
		Loading…
	
		Reference in New Issue