2017-11-10 18:27:39 +00:00
|
|
|
/*
|
|
|
|
* Mr. 4th Dimention - Allen Webster
|
|
|
|
*
|
|
|
|
* 10.11.2017
|
|
|
|
*
|
|
|
|
* Render target function implementations.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
// TOP
|
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
internal void
|
|
|
|
draw__begin_new_group(Render_Target *target){
|
|
|
|
Render_Group *group = 0;
|
|
|
|
if (target->group_last != 0){
|
|
|
|
if (target->group_last->vertex_list.vertex_count == 0){
|
|
|
|
group = target->group_last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (group == 0){
|
|
|
|
group = push_array_zero(&target->arena, Render_Group, 1);
|
|
|
|
sll_queue_push(target->group_first, target->group_last, group);
|
|
|
|
}
|
|
|
|
group->face_id = target->current_face_id;
|
|
|
|
group->clip_box = target->current_clip_box;
|
|
|
|
}
|
2017-11-10 18:27:39 +00:00
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
internal Render_Vertex_Array_Node*
|
|
|
|
draw__extend_group_vertex_memory(Arena *arena, Render_Vertex_List *list, i32 size){
|
|
|
|
Render_Vertex_Array_Node *node = push_array_zero(arena, Render_Vertex_Array_Node, 1);
|
|
|
|
sll_queue_push(list->first, list->last, node);
|
|
|
|
node->vertices = push_array(arena, Render_Vertex, size);
|
|
|
|
node->vertex_max = size;
|
|
|
|
return(node);
|
|
|
|
}
|
2017-11-11 00:58:47 +00:00
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
internal void
|
|
|
|
draw__write_vertices_in_current_group(Render_Target *target, Render_Vertex *vertices, i32 count){
|
|
|
|
if (count > 0){
|
|
|
|
Render_Group *group = target->group_last;
|
2019-07-25 19:54:58 +00:00
|
|
|
if (group == 0){
|
|
|
|
draw__begin_new_group(target);
|
|
|
|
group = target->group_last;
|
|
|
|
}
|
|
|
|
|
|
|
|
Render_Vertex_List *list = &group->vertex_list;
|
|
|
|
|
|
|
|
Render_Vertex_Array_Node *last = list->last;
|
|
|
|
|
|
|
|
Render_Vertex *tail_vertex = 0;
|
|
|
|
i32 tail_count = 0;
|
|
|
|
if (last != 0){
|
|
|
|
tail_vertex = last->vertices + last->vertex_count;
|
|
|
|
tail_count = last->vertex_max - last->vertex_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
i32 base_vertex_max = 64;
|
|
|
|
i32 transfer_count = clamp_top(count, tail_count);
|
|
|
|
if (transfer_count > 0){
|
|
|
|
block_copy_dynamic_array(tail_vertex, vertices, transfer_count);
|
|
|
|
last->vertex_count += transfer_count;
|
|
|
|
list->vertex_count += transfer_count;
|
|
|
|
base_vertex_max = last->vertex_max;
|
|
|
|
}
|
|
|
|
|
|
|
|
i32 count_left_over = count - transfer_count;
|
|
|
|
if (count_left_over > 0){
|
|
|
|
Render_Vertex *vertices_left_over = vertices + transfer_count;
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2019-07-25 19:54:58 +00:00
|
|
|
i32 next_node_size = (base_vertex_max + count_left_over)*2;
|
|
|
|
Render_Vertex_Array_Node *memory = draw__extend_group_vertex_memory(&target->arena, list, next_node_size);
|
|
|
|
block_copy_dynamic_array(memory->vertices, vertices_left_over, count_left_over);
|
|
|
|
memory->vertex_count += count_left_over;
|
|
|
|
list->vertex_count += count_left_over;
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
2019-07-25 19:54:58 +00:00
|
|
|
|
2017-11-11 00:58:47 +00:00
|
|
|
}
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
draw__set_face_id(Render_Target *target, Face_ID face_id){
|
|
|
|
if (target->current_face_id != face_id){
|
2019-07-25 19:54:58 +00:00
|
|
|
if (target->current_face_id != 0){
|
|
|
|
target->current_face_id = face_id;
|
|
|
|
draw__begin_new_group(target);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
target->current_face_id = face_id;
|
|
|
|
for (Render_Group *group = target->group_first;
|
|
|
|
group != 0;
|
|
|
|
group = group->next){
|
|
|
|
group->face_id = face_id;
|
|
|
|
}
|
|
|
|
}
|
2017-11-10 18:27:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
////////////////////////////////
|
|
|
|
|
2019-10-08 17:18:20 +00:00
|
|
|
internal Rect_f32
|
|
|
|
draw_set_clip(Render_Target *target, Rect_f32 clip_box){
|
|
|
|
Rect_f32 result = target->current_clip_box;
|
|
|
|
if (target->current_clip_box != clip_box){
|
|
|
|
target->current_clip_box = clip_box;
|
|
|
|
draw__begin_new_group(target);
|
2017-11-11 00:58:47 +00:00
|
|
|
}
|
2019-07-25 07:17:01 +00:00
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
begin_frame(Render_Target *target, void *font_set){
|
|
|
|
linalloc_clear(&target->arena);
|
|
|
|
target->group_first = 0;
|
|
|
|
target->group_last = 0;
|
|
|
|
target->current_face_id = 0;
|
2019-10-08 17:18:20 +00:00
|
|
|
target->current_clip_box = Rf32(0, 0, (f32)target->width, (f32)target->height);
|
2019-07-25 07:17:01 +00:00
|
|
|
target->font_set = font_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2019-10-03 17:57:44 +00:00
|
|
|
begin_render_section(Render_Target *target, i32 frame_index, f32 literal_dt, f32 animation_dt){
|
2019-07-25 07:17:01 +00:00
|
|
|
target->frame_index = frame_index;
|
|
|
|
target->literal_dt = literal_dt;
|
|
|
|
target->animation_dt = animation_dt;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
2019-10-03 17:57:44 +00:00
|
|
|
end_render_section(Render_Target *target){
|
2017-11-11 00:58:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
internal void
|
2019-10-08 19:02:04 +00:00
|
|
|
draw_rectangle_outline(Render_Target *target, Rect_f32 rect, f32 roundness, f32 thickness, u32 color){
|
|
|
|
if (roundness < epsilon_f32){
|
|
|
|
roundness = 0.f;
|
2019-10-08 17:18:20 +00:00
|
|
|
}
|
2019-10-08 19:02:04 +00:00
|
|
|
thickness = clamp_bot(1.f, thickness);
|
|
|
|
f32 half_thickness = thickness*0.5f;
|
2019-10-08 17:18:20 +00:00
|
|
|
|
2019-10-08 19:02:04 +00:00
|
|
|
Render_Vertex vertices[6] = {};
|
|
|
|
vertices[0].xy = V2f32(rect.x0, rect.y0);
|
|
|
|
vertices[1].xy = V2f32(rect.x1, rect.y0);
|
|
|
|
vertices[2].xy = V2f32(rect.x0, rect.y1);
|
|
|
|
vertices[3].xy = V2f32(rect.x1, rect.y0);
|
|
|
|
vertices[4].xy = V2f32(rect.x0, rect.y1);
|
|
|
|
vertices[5].xy = V2f32(rect.x1, rect.y1);
|
|
|
|
|
Avoid rendering rectangles (and characters) that are outside the window bounds.
While debugging an issue with the dx11 backend, I noticed that 4coder only clipped rectangles that are outside the screen vertically. Another potential issue (it might be the intended behavior) causes some things to not work with line wrapping, which means that we could have very long horizontal lines, causing a lot of vertices being sent through the render pipeline that will just be clipped after the vertex shader. This causes higher than necessary GPU memory usage, and low performance for things that aren't rendered in the end.
An example of problematic is:
```c
u8 data[ ] = {0,0,0,0,...,0}; // With a lot of zero, and no space between them.
```
This fix just checks that at least one vertex of each rectangle we try to draw is in the screen. It would be better to use the current clip rect, but it's not available at that point in the pipeline. If we want we can modify the API a little to pass it down, as a parameter to those functions.
Using RenderDoc, I saw the vertex count going from over 500K to 13K with this change, and the performance were from 57ms to 25ms. So perfs are not great (but still an improvement), but testing the bounds of 500K vertices is not free. Fixing the line wrapping issue would probably help getting back to reasonable frame rate.
2024-04-03 13:52:44 +00:00
|
|
|
// NOTE simon (03/04/24): If any vertex is in the render target bounds, we draw the rectangle.
|
|
|
|
// It would be better to use the current clip rect, but it's not available here. We could pass
|
|
|
|
// it down in the function signature if necessary.
|
|
|
|
Rect_f32 target_rect = Rf32( 0, 0, ( f32 ) target->width, ( f32 ) target->height );
|
|
|
|
b32 draw = false;
|
|
|
|
|
2019-10-08 19:02:04 +00:00
|
|
|
Vec2_f32 center = rect_center(rect);
|
|
|
|
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
|
|
|
|
vertices[i].uvw = V3f32(center.x, center.y, roundness);
|
|
|
|
vertices[i].color = color;
|
|
|
|
vertices[i].half_thickness = half_thickness;
|
Avoid rendering rectangles (and characters) that are outside the window bounds.
While debugging an issue with the dx11 backend, I noticed that 4coder only clipped rectangles that are outside the screen vertically. Another potential issue (it might be the intended behavior) causes some things to not work with line wrapping, which means that we could have very long horizontal lines, causing a lot of vertices being sent through the render pipeline that will just be clipped after the vertex shader. This causes higher than necessary GPU memory usage, and low performance for things that aren't rendered in the end.
An example of problematic is:
```c
u8 data[ ] = {0,0,0,0,...,0}; // With a lot of zero, and no space between them.
```
This fix just checks that at least one vertex of each rectangle we try to draw is in the screen. It would be better to use the current clip rect, but it's not available at that point in the pipeline. If we want we can modify the API a little to pass it down, as a parameter to those functions.
Using RenderDoc, I saw the vertex count going from over 500K to 13K with this change, and the performance were from 57ms to 25ms. So perfs are not great (but still an improvement), but testing the bounds of 500K vertices is not free. Fixing the line wrapping issue would probably help getting back to reasonable frame rate.
2024-04-03 13:52:44 +00:00
|
|
|
|
|
|
|
draw = draw || rect_contains_point( target_rect, vertices[ i ].xy );
|
|
|
|
}
|
|
|
|
|
|
|
|
draw = true;
|
|
|
|
|
|
|
|
if ( draw ) {
|
|
|
|
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
|
2019-10-08 17:18:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal void
|
|
|
|
draw_rectangle(Render_Target *target, Rect_f32 rect, f32 roundness, u32 color){
|
|
|
|
Vec2_f32 dim = rect_dim(rect);
|
2019-12-14 01:00:55 +00:00
|
|
|
draw_rectangle_outline(target, rect, roundness, Max(dim.x, dim.y), color);
|
2019-10-08 17:18:20 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 07:17:01 +00:00
|
|
|
internal void
|
2019-10-23 01:25:40 +00:00
|
|
|
draw_font_glyph(Render_Target *target, Face *face, u32 codepoint, Vec2_f32 p,
|
2020-05-09 16:55:01 +00:00
|
|
|
ARGB_Color color, Glyph_Flag flags, Vec2_f32 x_axis){
|
2019-07-25 07:17:01 +00:00
|
|
|
draw__set_face_id(target, face->id);
|
|
|
|
|
|
|
|
u16 glyph_index = 0;
|
2019-10-29 04:27:20 +00:00
|
|
|
if (!codepoint_index_map_read(&face->advance_map.codepoint_to_index,
|
|
|
|
codepoint, &glyph_index)){
|
2019-07-25 07:17:01 +00:00
|
|
|
glyph_index = 0;
|
|
|
|
}
|
|
|
|
Glyph_Bounds bounds = face->bounds[glyph_index];
|
|
|
|
Vec3_f32 texture_dim = face->texture_dim;
|
|
|
|
|
2020-05-09 16:55:01 +00:00
|
|
|
Render_Vertex vertices[6] = {};
|
|
|
|
|
2019-08-01 02:13:36 +00:00
|
|
|
Rect_f32 uv = bounds.uv;
|
2020-05-09 16:55:01 +00:00
|
|
|
vertices[0].uvw = V3f32(uv.x0, uv.y0, bounds.w);
|
|
|
|
vertices[1].uvw = V3f32(uv.x1, uv.y0, bounds.w);
|
|
|
|
vertices[2].uvw = V3f32(uv.x0, uv.y1, bounds.w);
|
|
|
|
vertices[5].uvw = V3f32(uv.x1, uv.y1, bounds.w);
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2020-05-09 16:55:01 +00:00
|
|
|
Vec2_f32 y_axis = V2f32(-x_axis.y, x_axis.x);
|
|
|
|
Vec2_f32 x_min = bounds.xy_off.x0*x_axis;
|
|
|
|
Vec2_f32 x_max = bounds.xy_off.x1*x_axis;
|
|
|
|
Vec2_f32 y_min = bounds.xy_off.y0*y_axis;
|
|
|
|
Vec2_f32 y_max = bounds.xy_off.y1*y_axis;
|
|
|
|
Vec2_f32 p_x_min = p + x_min;
|
|
|
|
Vec2_f32 p_x_max = p + x_max;
|
|
|
|
vertices[0].xy = p_x_min + y_min;
|
|
|
|
vertices[1].xy = p_x_max + y_min;
|
|
|
|
vertices[2].xy = p_x_min + y_max;
|
|
|
|
vertices[5].xy = p_x_max + y_max;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
Vec2_f32 xy_min = p + bounds.xy_off.x0*x_axis + bounds.xy_off.y0*y_axis;
|
|
|
|
Vec2_f32 xy_max = p + bounds.xy_off.x1*x_axis + bounds.xy_off.y1*y_axis;
|
|
|
|
|
|
|
|
vertices[0].xy = V2f32(xy_min.x, xy_min.y);
|
|
|
|
vertices[1].xy = V2f32(xy_max.x, xy_min.y);
|
|
|
|
vertices[2].xy = V2f32(xy_min.x, xy_max.y);
|
|
|
|
vertices[5].xy = V2f32(xy_max.x, xy_max.y);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
2019-07-25 07:17:01 +00:00
|
|
|
if (!HasFlag(flags, GlyphFlag_Rotate90)){
|
2019-10-23 01:25:40 +00:00
|
|
|
Rect_f32 xy = Rf32(p + bounds.xy_off.p0, p + bounds.xy_off.p1);
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2019-10-23 01:25:40 +00:00
|
|
|
vertices[0].xy = V2f32(xy.x0, xy.y1);
|
|
|
|
vertices[0].uvw = V3f32(uv.x0, uv.y1, bounds.w);
|
|
|
|
vertices[1].xy = V2f32(xy.x1, xy.y1);
|
|
|
|
vertices[1].uvw = V3f32(uv.x1, uv.y1, bounds.w);
|
|
|
|
vertices[2].xy = V2f32(xy.x0, xy.y0);
|
|
|
|
vertices[2].uvw = V3f32(uv.x0, uv.y0, bounds.w);
|
|
|
|
vertices[5].xy = V2f32(xy.x1, xy.y0);
|
|
|
|
vertices[5].uvw = V3f32(uv.x1, uv.y0, bounds.w);
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-10-23 01:25:40 +00:00
|
|
|
Rect_f32 xy = Rf32(p.x - bounds.xy_off.y1, p.y + bounds.xy_off.x0,
|
|
|
|
p.x - bounds.xy_off.y0, p.y + bounds.xy_off.x1);
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2019-10-23 01:25:40 +00:00
|
|
|
vertices[0].xy = V2f32(xy.x0, xy.y1);
|
|
|
|
vertices[0].uvw = V3f32(uv.x1, uv.y1, bounds.w);
|
|
|
|
vertices[1].xy = V2f32(xy.x1, xy.y1);
|
|
|
|
vertices[1].uvw = V3f32(uv.x1, uv.y0, bounds.w);
|
|
|
|
vertices[2].xy = V2f32(xy.x0, xy.y0);
|
|
|
|
vertices[2].uvw = V3f32(uv.x0, uv.y1, bounds.w);
|
|
|
|
vertices[5].xy = V2f32(xy.x1, xy.y0);
|
|
|
|
vertices[5].uvw = V3f32(uv.x0, uv.y0, bounds.w);
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
2020-05-09 16:55:01 +00:00
|
|
|
#endif
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2019-07-25 19:54:58 +00:00
|
|
|
vertices[3] = vertices[1];
|
|
|
|
vertices[4] = vertices[2];
|
2019-07-25 07:17:01 +00:00
|
|
|
|
Avoid rendering rectangles (and characters) that are outside the window bounds.
While debugging an issue with the dx11 backend, I noticed that 4coder only clipped rectangles that are outside the screen vertically. Another potential issue (it might be the intended behavior) causes some things to not work with line wrapping, which means that we could have very long horizontal lines, causing a lot of vertices being sent through the render pipeline that will just be clipped after the vertex shader. This causes higher than necessary GPU memory usage, and low performance for things that aren't rendered in the end.
An example of problematic is:
```c
u8 data[ ] = {0,0,0,0,...,0}; // With a lot of zero, and no space between them.
```
This fix just checks that at least one vertex of each rectangle we try to draw is in the screen. It would be better to use the current clip rect, but it's not available at that point in the pipeline. If we want we can modify the API a little to pass it down, as a parameter to those functions.
Using RenderDoc, I saw the vertex count going from over 500K to 13K with this change, and the performance were from 57ms to 25ms. So perfs are not great (but still an improvement), but testing the bounds of 500K vertices is not free. Fixing the line wrapping issue would probably help getting back to reasonable frame rate.
2024-04-03 13:52:44 +00:00
|
|
|
// NOTE simon (03/04/24): If any vertex is in the render target bounds, we draw the rectangle.
|
|
|
|
// It would be better to use the current clip rect, but it's not available here. We could pass
|
|
|
|
// it down in the function signature if necessary.
|
|
|
|
Rect_f32 target_rect = Rf32( 0, 0, ( f32 ) target->width, ( f32 ) target->height );
|
|
|
|
b32 draw = false;
|
|
|
|
|
2019-10-08 19:02:04 +00:00
|
|
|
for (i32 i = 0; i < ArrayCount(vertices); i += 1){
|
|
|
|
vertices[i].color = color;
|
|
|
|
vertices[i].half_thickness = 0.f;
|
Avoid rendering rectangles (and characters) that are outside the window bounds.
While debugging an issue with the dx11 backend, I noticed that 4coder only clipped rectangles that are outside the screen vertically. Another potential issue (it might be the intended behavior) causes some things to not work with line wrapping, which means that we could have very long horizontal lines, causing a lot of vertices being sent through the render pipeline that will just be clipped after the vertex shader. This causes higher than necessary GPU memory usage, and low performance for things that aren't rendered in the end.
An example of problematic is:
```c
u8 data[ ] = {0,0,0,0,...,0}; // With a lot of zero, and no space between them.
```
This fix just checks that at least one vertex of each rectangle we try to draw is in the screen. It would be better to use the current clip rect, but it's not available at that point in the pipeline. If we want we can modify the API a little to pass it down, as a parameter to those functions.
Using RenderDoc, I saw the vertex count going from over 500K to 13K with this change, and the performance were from 57ms to 25ms. So perfs are not great (but still an improvement), but testing the bounds of 500K vertices is not free. Fixing the line wrapping issue would probably help getting back to reasonable frame rate.
2024-04-03 13:52:44 +00:00
|
|
|
|
|
|
|
draw = draw || rect_contains_point( target_rect, vertices[ i ].xy );
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
2019-07-25 19:54:58 +00:00
|
|
|
|
Avoid rendering rectangles (and characters) that are outside the window bounds.
While debugging an issue with the dx11 backend, I noticed that 4coder only clipped rectangles that are outside the screen vertically. Another potential issue (it might be the intended behavior) causes some things to not work with line wrapping, which means that we could have very long horizontal lines, causing a lot of vertices being sent through the render pipeline that will just be clipped after the vertex shader. This causes higher than necessary GPU memory usage, and low performance for things that aren't rendered in the end.
An example of problematic is:
```c
u8 data[ ] = {0,0,0,0,...,0}; // With a lot of zero, and no space between them.
```
This fix just checks that at least one vertex of each rectangle we try to draw is in the screen. It would be better to use the current clip rect, but it's not available at that point in the pipeline. If we want we can modify the API a little to pass it down, as a parameter to those functions.
Using RenderDoc, I saw the vertex count going from over 500K to 13K with this change, and the performance were from 57ms to 25ms. So perfs are not great (but still an improvement), but testing the bounds of 500K vertices is not free. Fixing the line wrapping issue would probably help getting back to reasonable frame rate.
2024-04-03 13:52:44 +00:00
|
|
|
draw = true;
|
|
|
|
|
|
|
|
if ( draw ) {
|
|
|
|
draw__write_vertices_in_current_group(target, vertices, ArrayCount(vertices));
|
|
|
|
}
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
|
2019-12-18 00:19:03 +00:00
|
|
|
internal Vec2_f32
|
|
|
|
floor32(Vec2_f32 point){
|
2019-10-09 14:40:50 +00:00
|
|
|
point.x = f32_floor32(point.x);
|
|
|
|
point.y = f32_floor32(point.y);
|
2019-07-25 07:17:01 +00:00
|
|
|
return(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-10-23 01:25:40 +00:00
|
|
|
draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32 point,
|
|
|
|
ARGB_Color color, u32 flags, Vec2_f32 delta){
|
2019-07-25 07:17:01 +00:00
|
|
|
f32 total_delta = 0.f;
|
|
|
|
if (face != 0){
|
2019-10-09 14:40:50 +00:00
|
|
|
point = floor32(point);
|
2019-07-25 07:17:01 +00:00
|
|
|
|
2019-10-29 04:27:20 +00:00
|
|
|
f32 byte_advance = face->metrics.byte_advance;
|
|
|
|
f32 *byte_sub_advances = face->metrics.byte_sub_advances;
|
2019-07-25 07:17:01 +00:00
|
|
|
|
|
|
|
u8 *str = (u8*)string.str;
|
|
|
|
u8 *str_end = str + string.size;
|
|
|
|
|
|
|
|
Translation_State tran = {};
|
|
|
|
Translation_Emits emits = {};
|
|
|
|
|
|
|
|
for (u32 i = 0; str < str_end; ++str, ++i){
|
|
|
|
translating_fully_process_byte(&tran, *str, i, (i32)string.size, &emits);
|
|
|
|
|
|
|
|
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
|
|
|
TRANSLATION_DECL_GET_STEP(step, behavior, J, emits);
|
|
|
|
|
|
|
|
if (behavior.do_codepoint_advance){
|
|
|
|
u32 codepoint = step.value;
|
|
|
|
if (color != 0){
|
2020-05-02 03:59:36 +00:00
|
|
|
u32 draw_codepoint = step.value;
|
|
|
|
if (draw_codepoint == '\t'){
|
|
|
|
draw_codepoint = ' ';
|
|
|
|
}
|
2020-05-09 16:55:01 +00:00
|
|
|
draw_font_glyph(target, face, draw_codepoint, point, color, flags, delta);
|
2019-11-09 22:41:18 +00:00
|
|
|
}
|
2020-05-02 03:59:36 +00:00
|
|
|
local_const f32 internal_tab_width = 4.f;
|
|
|
|
f32 d = font_get_glyph_advance(&face->advance_map, &face->metrics, codepoint, internal_tab_width);
|
2019-07-25 07:17:01 +00:00
|
|
|
point += d*delta;
|
|
|
|
total_delta += d;
|
|
|
|
}
|
|
|
|
else if (behavior.do_number_advance){
|
|
|
|
u8 n = (u8)(step.value);
|
|
|
|
if (color != 0){
|
|
|
|
u8 cs[3];
|
|
|
|
cs[0] = '\\';
|
2019-10-01 20:04:45 +00:00
|
|
|
u8 nh = (n >> 4);
|
|
|
|
u8 nl = (n & 0xF);
|
|
|
|
u8 ch = '0' + nh;
|
|
|
|
u8 cl = '0' + nl;
|
|
|
|
if (nh > 0x9){
|
|
|
|
ch = ('A' - 0xA) + nh;
|
|
|
|
}
|
|
|
|
if (nl > 0x9){
|
|
|
|
cl = ('A' - 0xA) + nl;
|
|
|
|
}
|
|
|
|
cs[1] = ch;
|
|
|
|
cs[2] = cl;
|
|
|
|
|
2019-12-18 00:19:03 +00:00
|
|
|
Vec2_f32 pp = point;
|
2019-07-25 07:17:01 +00:00
|
|
|
for (u32 j = 0; j < 3; ++j){
|
2020-05-09 16:55:01 +00:00
|
|
|
draw_font_glyph(target, face, cs[j], pp, color, flags, delta);
|
2019-07-25 07:17:01 +00:00
|
|
|
pp += delta*byte_sub_advances[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
point += byte_advance*delta;
|
|
|
|
total_delta += byte_advance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-15 08:38:28 +00:00
|
|
|
}
|
2019-07-25 07:17:01 +00:00
|
|
|
|
|
|
|
return(total_delta);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-12-18 00:19:03 +00:00
|
|
|
draw_string(Render_Target *target, Face *face, String_Const_u8 string, Vec2_f32 point, u32 color){
|
|
|
|
return(draw_string(target, face, string, point, color, 0, V2f32(1.f, 0.f)));
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-12-18 00:19:03 +00:00
|
|
|
draw_string(Render_Target *target, Face *face, u8 *str, Vec2_f32 point, u32 color, u32 flags, Vec2_f32 delta){
|
2019-07-25 19:54:58 +00:00
|
|
|
return(draw_string(target, face, SCu8(str), point, color, flags, delta));
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-12-18 00:19:03 +00:00
|
|
|
draw_string(Render_Target *target, Face *face, u8 *str, Vec2_f32 point, u32 color){
|
|
|
|
return(draw_string(target, face, SCu8(str), point, color, 0, V2f32(1.f, 0.f)));
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-07-25 19:54:58 +00:00
|
|
|
font_string_width(Render_Target *target, Face *face, String_Const_u8 str){
|
2019-12-18 00:19:03 +00:00
|
|
|
return(draw_string(target, face, str, V2f32(0, 0), 0, 0, V2f32(0, 0)));
|
2019-07-25 07:17:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
internal f32
|
2019-07-25 19:54:58 +00:00
|
|
|
font_string_width(Render_Target *target, Face *face, u8 *str){
|
2019-12-18 00:19:03 +00:00
|
|
|
return(draw_string(target, face, SCu8(str), V2f32(0, 0), 0, 0, V2f32(0, 0)));
|
2017-11-10 18:27:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// BOTTOM
|
|
|
|
|