Working towards getting the library to an alpha release state
This commit is contained in:
parent
488e5ba67f
commit
50dd6130c8
@ -18,8 +18,8 @@ Features:
|
||||
* Clear the caches at any-time!
|
||||
* Robust quality of life features:
|
||||
* Tracks text layers!
|
||||
* Push and pop stack for font, font_size, view, position, scale and zoom!
|
||||
* Enforce even only font-sizing
|
||||
* Push and pop stack for font, font_size, colour, view, position, scale and zoom!
|
||||
* Enforce even only font-sizing [TODO]
|
||||
* Snap-positining to view for better hinting
|
||||
* Basic or advanced text shaping via Harfbuzz
|
||||
* All rendering is real-time, triangulation done on the CPU, vertex rendering and texture blitting on the gpu.
|
||||
|
@ -2,8 +2,6 @@ package vetext
|
||||
|
||||
/*
|
||||
Note(Ed): This may be seperated in the future into another file dedending on how much is involved with supportin ear-clipping triangulation.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
import "base:runtime"
|
||||
@ -113,7 +111,12 @@ Glyph_Draw_Buffer :: struct{
|
||||
|
||||
// Contructs a quad mesh for bliting a texture from one render target (src uv0 & 1) to the destination rendertarget (p0, p1)
|
||||
@(optimization_mode="favor_size")
|
||||
blit_quad :: #force_inline proc ( draw_list : ^Draw_List, p0 : Vec2 = {0, 0}, p1 : Vec2 = {1, 1}, uv0 : Vec2 = {0, 0}, uv1 : Vec2 = {1, 1} )
|
||||
blit_quad :: #force_inline proc ( draw_list : ^Draw_List,
|
||||
p0 : Vec2 = {0, 0},
|
||||
p1 : Vec2 = {1, 1},
|
||||
uv0 : Vec2 = {0, 0},
|
||||
uv1 : Vec2 = {1, 1}
|
||||
)
|
||||
{
|
||||
// profile(#procedure)
|
||||
v_offset := cast(u32) len(draw_list.vertices)
|
||||
@ -250,7 +253,16 @@ generate_glyph_pass_draw_list :: proc(draw_list : ^Draw_List, path : ^[dynamic]V
|
||||
}
|
||||
|
||||
// Just a warpper of generate_shape_draw_list for handling an array of shapes
|
||||
generate_shapes_draw_list :: #force_inline proc ( ctx : ^Context, font : Font_ID, colour : RGBAN, entry : Entry, px_size, font_scale : f32, position, scale : Vec2, shapes : []Shaped_Text )
|
||||
generate_shapes_draw_list :: #force_inline proc ( ctx : ^Context,
|
||||
font : Font_ID,
|
||||
colour : RGBAN,
|
||||
entry : Entry,
|
||||
px_size : f32,
|
||||
font_scale : f32,
|
||||
position : Vec2,
|
||||
scale : Vec2,
|
||||
shapes : []Shaped_Text
|
||||
)
|
||||
{
|
||||
assert(len(shapes) > 0)
|
||||
for shape in shapes {
|
||||
|
@ -88,6 +88,11 @@ fill :: proc {
|
||||
slice.fill,
|
||||
}
|
||||
|
||||
max :: proc {
|
||||
linalg.max_single,
|
||||
linalg.max_double,
|
||||
}
|
||||
|
||||
make :: proc {
|
||||
builtin.make_dynamic_array,
|
||||
builtin.make_dynamic_array_len,
|
||||
|
@ -22,11 +22,6 @@ Shape_Key :: u32
|
||||
Ideally the user should resolve this shape once and cache/store it on their side.
|
||||
They have the best ability to avoid costly lookups to streamline
|
||||
a hot path to only focusing on draw list generation that must be computed every frame.
|
||||
|
||||
For ease of use the cache does a relatively good job and only adds a
|
||||
few hundred nano-seconds to resolve a shape's lookup from its source specification.
|
||||
If your doing something very heavy though (tens-of thousands +) your not
|
||||
going to be satisfied with keeping that in the iteration).
|
||||
*/
|
||||
Shaped_Text :: struct #packed {
|
||||
glyph : [dynamic]Glyph,
|
||||
@ -36,6 +31,8 @@ Shaped_Text :: struct #packed {
|
||||
bounds : [dynamic]Range2,
|
||||
end_cursor_pos : Vec2,
|
||||
size : Vec2,
|
||||
font_id : Font_ID,
|
||||
// TODO(Ed): We need to track the font here for usage in user interface when directly drawing the shape.
|
||||
}
|
||||
|
||||
// Ease of use cache, can handle thousands of lookups per frame with ease.
|
||||
|
@ -104,7 +104,7 @@ Context :: struct {
|
||||
// the draw_list result by the same amount.
|
||||
px_scalar : f32, // Improves hinting, positioning, etc. Can make zoomed out text too jagged.
|
||||
|
||||
default_curve_quality : i32,
|
||||
default_curve_quality : i32,
|
||||
}
|
||||
|
||||
Init_Atlas_Params :: struct {
|
||||
@ -336,6 +336,15 @@ startup :: proc( ctx : ^Context, parser_kind : Parser_Kind = .STB_TrueType, // N
|
||||
|
||||
parser_init( & ctx.parser_ctx, parser_kind )
|
||||
shaper_init( & ctx.shaper_ctx )
|
||||
|
||||
// Set the default stack values
|
||||
// Will be popped on shutdown
|
||||
// push_colour(ctx, {1, 1, 1, 1})
|
||||
// push_font_size(ctx, 36)
|
||||
// push_view(ctx, { 0, 0 })
|
||||
// push_position(ctx, {0, 0})
|
||||
// push_scale(ctx, 1.0)
|
||||
// push_zoom(ctx, 1.0)
|
||||
}
|
||||
|
||||
hot_reload :: proc( ctx : ^Context, allocator : Allocator )
|
||||
@ -399,6 +408,13 @@ shutdown :: proc( ctx : ^Context )
|
||||
shape_cache := & ctx.shape_cache
|
||||
draw_list := & ctx.draw_list
|
||||
|
||||
// pop_colour(ctx)
|
||||
// pop_font_size(ctx)
|
||||
// pop_view(ctx)
|
||||
// pop_position(ctx)
|
||||
// pop_scale(ctx)
|
||||
// pop_zoom(ctx)
|
||||
|
||||
for & entry in ctx.entries {
|
||||
unload_font( ctx, entry.id )
|
||||
}
|
||||
@ -544,12 +560,6 @@ unload_font :: proc( ctx : ^Context, font : Font_ID )
|
||||
|
||||
//#region("scoping")
|
||||
|
||||
configure_snap :: #force_inline proc( ctx : ^Context, snap_width, snap_height : u32 ) {
|
||||
assert( ctx != nil )
|
||||
ctx.snap_width = f32(snap_width)
|
||||
ctx.snap_height = f32(snap_height)
|
||||
}
|
||||
|
||||
/* Scope stacking ease of use interface.
|
||||
|
||||
View: Extents in 2D for the relative space the the text is being drawn within.
|
||||
@ -593,7 +603,7 @@ auto_pop_position :: #force_inline proc( ctx : ^Context, view : Vec2 )
|
||||
@(deferred_in = auto_pop_scale)
|
||||
scope_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) }
|
||||
push_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); append(& ctx.stack.scale, scale ) }
|
||||
pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) }
|
||||
pop_scale :: #force_inline proc( ctx : ^Context, ) { assert(ctx != nil); pop(& ctx.stack.scale) }
|
||||
auto_pop_scale :: #force_inline proc( ctx : ^Context, scale : Vec2 ) { assert(ctx != nil); pop(& ctx.stack.scale) }
|
||||
|
||||
@(deferred_in = auto_pop_zoom )
|
||||
@ -635,19 +645,21 @@ auto_pop_vpz :: #force_inline proc( ctx : ^Context, camera : VPZ_Transform ) {
|
||||
get_cursor_pos :: #force_inline proc "contextless" ( ctx : Context ) -> Vec2 { return ctx.cursor_pos }
|
||||
|
||||
// Does nothing when view is 1 or 0.
|
||||
get_snapped_position :: #force_inline proc "contextless" ( ctx : Context, position : Vec2 ) -> (snapped_position : Vec2) {
|
||||
snap_width := max(ctx.snap_width, 1)
|
||||
snap_height := max(ctx.snap_height, 1)
|
||||
snap_quotient := 1 / Vec2 { snap_width, snap_height }
|
||||
get_snapped_position :: #force_inline proc "contextless" ( position : Vec2, view : Vec2 ) -> (snapped_position : Vec2) {
|
||||
snap_quotient := 1 / Vec2 { max(view.x, 1), max(view.y, 1) }
|
||||
should_snap := view * snap_quotient
|
||||
snapped_position = position
|
||||
snapped_position.x = ceil(position.x * snap_width ) * snap_quotient.x
|
||||
snapped_position.y = ceil(position.y * snap_height) * snap_quotient.y
|
||||
return
|
||||
snapped_position.x = ceil(position.x * view.x) * snap_quotient.x
|
||||
snapped_position.y = ceil(position.y * view.y) * snap_quotient.y
|
||||
snapped_position *= should_snap
|
||||
snapped_position.x = max(snapped_position.x, position.x)
|
||||
snapped_position.y = max(snapped_position.y, position.y)
|
||||
return snapped_position
|
||||
}
|
||||
|
||||
set_alpha_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.alpha_sharpen = scalar }
|
||||
set_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); ctx.colour = colour }
|
||||
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
|
||||
set_alpha_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.alpha_sharpen = scalar }
|
||||
set_colour :: #force_inline proc( ctx : ^Context, colour : RGBAN ) { assert(ctx != nil); ctx.colour = colour }
|
||||
set_px_scalar :: #force_inline proc( ctx : ^Context, scalar : f32 ) { assert(ctx != nil); ctx.px_scalar = scalar }
|
||||
|
||||
set_snap_glyph_shape_position :: #force_inline proc( ctx : ^Context, should_snap : b32 ) {
|
||||
assert(ctx != nil)
|
||||
@ -661,7 +673,6 @@ set_snap_glyph_render_height :: #force_inline proc( ctx : ^Context, should_snap
|
||||
|
||||
// Non-scoping context. The most fundamental interface-level draw shape procedure.
|
||||
// (everything else is either batching/pipelining or quality of life warppers)
|
||||
// Note: Prefer over draw_text_normalized_space if possible to resolve shape once persistently or at least once per frame or non-dirty state.
|
||||
@(optimization_mode="favor_size")
|
||||
draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
font : Font_ID,
|
||||
@ -670,7 +681,7 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
view : Vec2,
|
||||
position : Vec2,
|
||||
scale : Vec2,
|
||||
zoom : f32,
|
||||
zoom : f32, // TODO(Ed): Implement zoom support
|
||||
shape : Shaped_Text
|
||||
)
|
||||
{
|
||||
@ -678,15 +689,13 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
assert( ctx != nil )
|
||||
assert( font >= 0 && int(font) < len(ctx.entries) )
|
||||
|
||||
adjusted_position := get_snapped_position( ctx^, position )
|
||||
adjusted_position := get_snapped_position( position, view )
|
||||
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_colour := colour
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
@ -704,15 +713,15 @@ draw_text_shape_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
|
||||
// Non-scoping context. The most fundamental interface-level draw text procedure.
|
||||
// (everything else is either batching/pipelining or quality of life warppers)
|
||||
// Note: shape lookup can be expensive on high call usage.
|
||||
draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
@(optimization_mode = "favor_size")
|
||||
draw_text_normalized_space :: proc( ctx : ^Context,
|
||||
font : Font_ID,
|
||||
px_size : f32,
|
||||
colour : RGBAN,
|
||||
view : Vec2,
|
||||
position : Vec2,
|
||||
scale : Vec2,
|
||||
zoom : f32,
|
||||
zoom : f32, // TODO(Ed): Implement Zoom support
|
||||
text_utf8 : string
|
||||
)
|
||||
{
|
||||
@ -720,15 +729,14 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
assert( ctx != nil )
|
||||
assert( font >= 0 && int(font) < len(ctx.entries) )
|
||||
assert( len(text_utf8) > 0 )
|
||||
assert( ctx.snap_width > 0 && ctx.snap_height > 0 )
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_position := get_snapped_position( ctx^, position )
|
||||
adjusted_position := get_snapped_position( position, view )
|
||||
|
||||
colour := ctx.colour
|
||||
colour.a = 1.0 + ctx.alpha_sharpen
|
||||
adjusted_colour := colour
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
// Does nothing when px_scalar is 1.0
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
@ -744,7 +752,7 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
)
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
ctx.px_scalar,
|
||||
colour,
|
||||
adjusted_colour,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
@ -753,88 +761,210 @@ draw_text_normalized_space :: #force_inline proc( ctx : ^Context,
|
||||
)
|
||||
}
|
||||
|
||||
draw_shape :: #force_inline proc( ctx : ^Context, position, scale : Vec2, shape : Shaped_Text ) {
|
||||
// peek_position
|
||||
}
|
||||
|
||||
draw_text :: #force_inline proc( ctx : ^Context, text_utf8 : string, position, scale : Vec2 ) {
|
||||
|
||||
}
|
||||
|
||||
Text_Layer_Elem :: struct {
|
||||
text : string,
|
||||
// Equivalent to draw_text_shape_normalized_space, however position's units is scaled to view and must be normalized.
|
||||
@(optimization_mode="favor_size")
|
||||
draw_text_shape_view_space :: #force_inline proc( ctx : ^Context,
|
||||
font : Font_ID,
|
||||
px_size : f32,
|
||||
colour : RGBAN,
|
||||
view : Vec2,
|
||||
position : Vec2,
|
||||
scale : Vec2,
|
||||
font : Font_ID,
|
||||
px_size : f32,
|
||||
zoom : f32,
|
||||
colour : RGBAN,
|
||||
}
|
||||
|
||||
// Batch a layer of text. Use get_draw_list_layer to process the layer immediately after.
|
||||
draw_text_layer :: #force_inline proc( ctx : ^Context, layer : []Text_Layer_Elem )
|
||||
scale : Vec2,
|
||||
zoom : f32, // TODO(Ed): Implement zoom support
|
||||
shape : Shaped_Text
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
assert( len(layer) > 0 )
|
||||
assert( font >= 0 && int(font) < len(ctx.entries) )
|
||||
|
||||
shapes := make( []Shaped_Text, len(layer) )
|
||||
for elem in layer
|
||||
{
|
||||
assert( elem.font >= 0 && int(elem.font) < len(ctx.entries) )
|
||||
norm_position := position * (1 / view)
|
||||
|
||||
for elem, id in layer
|
||||
{
|
||||
entry := ctx.entries[ elem.font ]
|
||||
view := view; view.x = max(view.x, 1); view.y = max(view.y, 1)
|
||||
adjusted_position := get_snapped_position( norm_position, view )
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
// colour := ctx.colour
|
||||
// colour.a = 1.0 + ctx.alpha_sharpen
|
||||
adjusted_colour := colour
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
// adjusted_position := get_snapped_position( ctx^, elem.position )
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
// font_scale := parser_scale( entry.parser_info, elem.px_size )
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
ctx.px_scalar,
|
||||
adjusted_colour,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
position,
|
||||
target_scale,
|
||||
)
|
||||
}
|
||||
|
||||
target_px_size := elem.px_size * ctx.px_scalar
|
||||
// target_scale := elem.scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
// Equivalent to draw_text_normalized_space, however position's units is scaled to view and must be normalized.
|
||||
@(optimization_mode = "favor_size")
|
||||
draw_text_view_space :: proc(ctx : ^Context,
|
||||
font : Font_ID,
|
||||
px_size : f32,
|
||||
colour : RGBAN,
|
||||
view : Vec2,
|
||||
view_position : Vec2,
|
||||
scale : Vec2,
|
||||
zoom : f32, // TODO(Ed): Implement Zoom support
|
||||
text_utf8 : string
|
||||
)
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
assert( font >= 0 && int(font) < len(ctx.entries) )
|
||||
assert( len(text_utf8) > 0 )
|
||||
|
||||
assert( len(elem.text) > 0 )
|
||||
shape := shaper_shape_text_cached( elem.text,
|
||||
& ctx.shaper_ctx,
|
||||
& ctx.shape_cache,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
elem.font,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
shapes[id] = shape
|
||||
}
|
||||
}
|
||||
ctx.cursor_pos = {}
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
for elem, id in layer {
|
||||
entry := ctx.entries[ elem.font ]
|
||||
norm_position := view_position * (1 / view)
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
adjusted_position := get_snapped_position( norm_position, view )
|
||||
|
||||
colour := ctx.colour
|
||||
colour.a = 1.0 + ctx.alpha_sharpen
|
||||
adjusted_colour := colour
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
adjusted_position := get_snapped_position( ctx^, elem.position )
|
||||
// Does nothing when px_scalar is 1.0
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
// font_scale := parser_scale( entry.parser_info, elem.px_size )
|
||||
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, ctx.atlas, vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
ctx.px_scalar,
|
||||
adjusted_colour,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
adjusted_position,
|
||||
target_scale,
|
||||
)
|
||||
}
|
||||
|
||||
target_px_size := elem.px_size * ctx.px_scalar
|
||||
target_scale := elem.scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
@(optimization_mode = "favor_size")
|
||||
draw_shape :: proc( ctx : ^Context, position, scale : Vec2, shape : Shaped_Text )
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
|
||||
generate_shapes_draw_list(ctx, elem.font, elem.colour, entry, target_px_size, target_font_scale, adjusted_position, target_scale, shapes )
|
||||
}
|
||||
stack := & ctx.stack
|
||||
assert(len(stack.font) > 0)
|
||||
assert(len(stack.view) > 0)
|
||||
assert(len(stack.colour) > 0)
|
||||
assert(len(stack.position) > 0)
|
||||
assert(len(stack.scale) > 0)
|
||||
assert(len(stack.font_size) > 0)
|
||||
assert(len(stack.zoom) > 0)
|
||||
|
||||
// TODO(Ed): This should be taken from the shape instead (you cannot use a different font with a shape)
|
||||
font := peek(stack.font)
|
||||
assert( font >= 0 &&int(font) < len(ctx.entries) )
|
||||
|
||||
view := peek(stack.view);
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_colour := peek(stack.colour)
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
// TODO(Ed): Implement zoom for draw_text
|
||||
zoom := peek(stack.zoom)
|
||||
|
||||
absolute_position := peek(stack.position) + position
|
||||
absolute_scale := peek(stack.scale) * scale
|
||||
|
||||
adjusted_position := get_snapped_position( absolute_position, view )
|
||||
|
||||
px_size := peek(stack.font_size)
|
||||
|
||||
// Does nothing when px_scalar is 1.0
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := absolute_scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
ctx.px_scalar,
|
||||
adjusted_colour,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
adjusted_position,
|
||||
target_scale,
|
||||
)
|
||||
}
|
||||
|
||||
@(optimization_mode = "favor_size")
|
||||
draw_text :: proc( ctx : ^Context, position, scale : Vec2, text_utf8 : string )
|
||||
{
|
||||
profile(#procedure)
|
||||
assert( ctx != nil )
|
||||
assert( len(text_utf8) > 0 )
|
||||
|
||||
stack := & ctx.stack
|
||||
assert(len(stack.font) > 0)
|
||||
assert(len(stack.view) > 0)
|
||||
assert(len(stack.colour) > 0)
|
||||
assert(len(stack.position) > 0)
|
||||
assert(len(stack.scale) > 0)
|
||||
assert(len(stack.font_size) > 0)
|
||||
assert(len(stack.zoom) > 0)
|
||||
|
||||
font := peek(stack.font)
|
||||
assert( font >= 0 &&int(font) < len(ctx.entries) )
|
||||
|
||||
view := peek(stack.view);
|
||||
|
||||
ctx.cursor_pos = {}
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
adjusted_colour := peek(stack.colour)
|
||||
adjusted_colour.a = 1.0 + ctx.alpha_sharpen
|
||||
|
||||
// TODO(Ed): Implement zoom for draw_text
|
||||
zoom := peek(stack.zoom)
|
||||
|
||||
absolute_position := peek(stack.position) + position
|
||||
absolute_scale := peek(stack.scale) * scale
|
||||
|
||||
adjusted_position := get_snapped_position( absolute_position, view )
|
||||
|
||||
px_size := peek(stack.font_size)
|
||||
|
||||
// Does nothing when px_scalar is 1.0
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_scale := absolute_scale * (1 / ctx.px_scalar)
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shape := shaper_shape_text_cached( text_utf8, & ctx.shaper_ctx, & ctx.shape_cache, ctx.atlas, vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
ctx.cursor_pos = generate_shape_draw_list( & ctx.draw_list, shape, & ctx.atlas, & ctx.glyph_buffer,
|
||||
ctx.px_scalar,
|
||||
adjusted_colour,
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
adjusted_position,
|
||||
target_scale,
|
||||
)
|
||||
}
|
||||
|
||||
get_draw_list :: #force_inline proc( ctx : ^Context, optimize_before_returning := true ) -> ^Draw_List {
|
||||
@ -889,11 +1019,9 @@ measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
|
||||
entry := ctx.entries[font]
|
||||
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
downscale := 1 / ctx.px_scalar
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
downscale := 1 / ctx.px_scalar
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shaped := shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
@ -902,8 +1030,8 @@ measure_text_size :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
font_scale_upscaled,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
return shaped.size * downscale
|
||||
@ -934,10 +1062,8 @@ shape_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
return shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
@ -946,8 +1072,8 @@ shape_text_latin :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
font_scale_upscaled,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_latin
|
||||
)
|
||||
}
|
||||
@ -958,10 +1084,8 @@ shape_text_advanced :: #force_inline proc( ctx : ^Context, font : Font_ID, px_si
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
font_scale := parser_scale( entry.parser_info, px_size )
|
||||
|
||||
px_size_upscaled := px_size * ctx.px_scalar
|
||||
font_scale_upscaled := parser_scale( entry.parser_info, px_size_upscaled )
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
return shaper_shape_text_cached( text_utf8,
|
||||
& ctx.shaper_ctx,
|
||||
@ -970,25 +1094,55 @@ shape_text_advanced :: #force_inline proc( ctx : ^Context, font : Font_ID, px_si
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
font,
|
||||
entry,
|
||||
px_size_upscaled,
|
||||
font_scale_upscaled,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
shaper_shape_text_uncached_advanced
|
||||
)
|
||||
}
|
||||
|
||||
// User handled shaped text. Will not be cached
|
||||
// @(disabled = true)
|
||||
shape_text_latin_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, text_utf8 : string, entry : ^Entry, shape : ^Shaped_Text )
|
||||
shape_text_latin_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size: f32, text_utf8 : string, shape : ^Shaped_Text )
|
||||
{
|
||||
assert(false)
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shaper_shape_text_latin(& ctx.shaper_ctx,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
text_utf8,
|
||||
shape
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// User handled shaped text. Will not be cached
|
||||
// @(disabled = true)
|
||||
shape_text_advanced_uncahed :: #force_inline proc( ctx : ^Context, font : Font_ID, text_utf8 : string, entry : ^Entry, shape : ^Shaped_Text )
|
||||
shape_text_advanced_uncached :: #force_inline proc( ctx : ^Context, font : Font_ID, px_size: f32, text_utf8 : string, shape : ^Shaped_Text )
|
||||
{
|
||||
assert(false)
|
||||
profile(#procedure)
|
||||
assert( len(text_utf8) > 0 )
|
||||
entry := ctx.entries[ font ]
|
||||
|
||||
target_px_size := px_size * ctx.px_scalar
|
||||
target_font_scale := parser_scale( entry.parser_info, target_px_size )
|
||||
|
||||
shaper_shape_text_uncached_advanced(& ctx.shaper_ctx,
|
||||
ctx.atlas,
|
||||
vec2(ctx.glyph_buffer.size),
|
||||
entry,
|
||||
target_px_size,
|
||||
target_font_scale,
|
||||
text_utf8,
|
||||
shape
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ startup :: proc( prof : ^SpallProfiler, persistent_mem, frame_mem, transient_mem
|
||||
text_snap_glyph_shape_position = false
|
||||
text_snap_glyph_render_height = false
|
||||
text_size_screen_scalar = 2
|
||||
text_size_canvas_scalar = 0.2
|
||||
text_size_canvas_scalar = 2
|
||||
text_alpha_sharpen = 0.1
|
||||
}
|
||||
|
||||
|
@ -56,9 +56,10 @@ render_mode_2d_workspace :: proc( screen_extent : Vec2, cam : Camera, input : In
|
||||
cam_zoom_ratio := 1.0 / cam.zoom
|
||||
screen_size := screen_extent * 2
|
||||
|
||||
// TODO(Ed): Eventually will be the viewport extents
|
||||
font_provider_set_px_scalar( app_config().text_size_canvas_scalar )
|
||||
ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
|
||||
|
||||
// TODO(Ed): Eventually will be the viewport extents
|
||||
// ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
|
||||
// ve.configure_snap( ve_ctx, 0, 0 )
|
||||
|
||||
Render_Debug:
|
||||
@ -124,7 +125,7 @@ render_mode_screenspace :: proc( screen_extent : Extents2, screen_ui : ^UI_State
|
||||
screen_ratio := screen_size.x * ( 1.0 / screen_size.y )
|
||||
|
||||
font_provider_set_px_scalar( app_config().text_size_screen_scalar )
|
||||
ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
|
||||
// ve.configure_snap( ve_ctx, u32(screen_size.x), u32(screen_size.y) )
|
||||
|
||||
render_screen_ui( screen_extent, screen_ui, ve_ctx, ve_render )
|
||||
|
||||
@ -908,26 +909,29 @@ draw_rect_rounded_border :: proc(rect: Range2, radii: [4]f32, border_width: f32,
|
||||
// Draw text using a string and normalized render coordinates
|
||||
draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White, scale : f32 = 1.0 )
|
||||
{
|
||||
state := get_state(); using state
|
||||
width := app_window.extent.x * 2
|
||||
height := app_window.extent.y * 2
|
||||
|
||||
// over_sample : f32 = f32(config.font_size_screen_scalar)
|
||||
screen_extent := get_state().app_window.extent // TODO(Ed): Pass this in instead..
|
||||
screen_size := screen_extent * 2
|
||||
|
||||
target_size := font_size
|
||||
// target_size *= over_sample
|
||||
|
||||
ve_id, resolved_size := font_provider_resolve_draw_id( id, target_size )
|
||||
color_norm := normalize_rgba8(color)
|
||||
|
||||
screen_size_norm := 1 / Vec2 { width, height }
|
||||
screen_size_norm := 1 / screen_size
|
||||
draw_scale := screen_size_norm * scale
|
||||
|
||||
draw_scale := screen_size_norm * scale
|
||||
// draw_scale /= over_sample
|
||||
|
||||
// ve.set_px_scalar( & font_provider_ctx.ve_ctx, config.font_size_screen_scalar )
|
||||
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
|
||||
ve.draw_text_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32(resolved_size), color_norm, {}, pos, draw_scale, 1.0, text )
|
||||
ve_ctx := & get_state().font_provider_ctx.ve_ctx
|
||||
ve.set_colour(ve_ctx, color_norm )
|
||||
ve.draw_text_normalized_space(ve_ctx,
|
||||
ve_id,
|
||||
f32(resolved_size),
|
||||
color_norm,
|
||||
screen_size,
|
||||
pos,
|
||||
draw_scale,
|
||||
1.0,
|
||||
text
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@ -935,8 +939,8 @@ draw_text_string_pos_norm :: #force_inline proc( text : string, id : FontID, fon
|
||||
draw_text_string_pos_extent :: #force_inline proc( text : string, id : FontID, font_size : f32, pos : Vec2, color := Color_White )
|
||||
{
|
||||
profile(#procedure)
|
||||
state := get_state(); using state
|
||||
screen_size := app_window.extent * 2
|
||||
screen_extent := get_state().app_window.extent // TODO(Ed): Pass this in instead..
|
||||
screen_size := screen_extent * 2
|
||||
render_pos := screen_to_render_pos(pos)
|
||||
normalized_pos := render_pos * (1.0 / screen_size)
|
||||
|
||||
@ -1002,7 +1006,7 @@ draw_text_string_pos_extent_zoomed :: #force_inline proc( text : string, id : Fo
|
||||
ve_id,
|
||||
f32(resolved_size),
|
||||
color_norm,
|
||||
{},
|
||||
screen_size,
|
||||
normalized_pos,
|
||||
text_scale,
|
||||
1.0,
|
||||
@ -1043,7 +1047,16 @@ draw_text_shape_pos_extent_zoomed :: #force_inline proc( shape : ShapedText, id
|
||||
color_norm := normalize_rgba8(color)
|
||||
// ve.set_px_scalar( & get_state().font_provider_ctx.ve_ctx, config.font_size_canvas_scalar )
|
||||
ve.set_colour( & font_provider_ctx.ve_ctx, color_norm )
|
||||
ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx, ve_id, f32_resolved_size, color_norm, {}, normalized_pos, text_scale, 1.0, shape )
|
||||
ve.draw_text_shape_normalized_space( & font_provider_ctx.ve_ctx,
|
||||
ve_id,
|
||||
f32_resolved_size,
|
||||
color_norm,
|
||||
screen_size,
|
||||
normalized_pos,
|
||||
text_scale,
|
||||
1.0,
|
||||
shape
|
||||
)
|
||||
}
|
||||
|
||||
// TODO(Ed): Eventually the workspace will need a viewport for drawing text
|
||||
|
Loading…
x
Reference in New Issue
Block a user