cleaning up opengl code

This commit is contained in:
Allen Webster 2017-11-10 13:27:39 -05:00
parent d04dd8879b
commit c0bf8966eb
14 changed files with 676 additions and 861 deletions

View File

@ -2313,7 +2313,12 @@ App_Step_Sig(app_step){
begin_render_section(target, system); begin_render_section(target, system);
target->clip_top = -1; target->clip_top = -1;
draw_push_clip(target, rect_from_target(target)); i32_Rect target_rect = {0};
target_rect.x0 = 0;
target_rect.y0 = 0;
target_rect.x1 = target->width;
target_rect.y1 = target->height;
draw_push_clip(target, target_rect);
Command_Data *command = cmd; Command_Data *command = cmd;
USE_PANEL(active_panel); USE_PANEL(active_panel);

View File

@ -19,7 +19,6 @@
#include "4ed_math.h" #include "4ed_math.h"
#include "4ed_system.h" #include "4ed_system.h"
// TODO(allen): set in compilation line
#define PREFERRED_ALIGNMENT 8 #define PREFERRED_ALIGNMENT 8
#define USE_DEBUG_MEMORY #define USE_DEBUG_MEMORY
@ -33,7 +32,8 @@
# include "4ed_debug_mem.h" # include "4ed_debug_mem.h"
#endif #endif
#include "4ed_rendering.h" #include "4ed_render_format.h"
#include "4ed_render_target.h"
#include "4ed.h" #include "4ed.h"
#include "4ed_buffer_model.h" #include "4ed_buffer_model.h"
@ -43,7 +43,9 @@
#include "4ed_doubly_linked_list.cpp" #include "4ed_doubly_linked_list.cpp"
#include "4ed_translation.cpp" #include "4ed_translation.cpp"
#include "4ed_rendering_helper.cpp"
#include "4ed_render_target.cpp"
#include "4ed_render_fill.cpp"
#include "4ed_style.h" #include "4ed_style.h"
#include "4ed_style.cpp" #include "4ed_style.cpp"

View File

@ -5879,7 +5879,7 @@ draw_file_loaded(System_Functions *system, View *view, Models *models, i32_Rect
draw_rectangle_outline(target, char_rect, mark_color); draw_rectangle_outline(target, char_rect, mark_color);
} }
if (item->codepoint != 0){ if (item->codepoint != 0){
font_draw_glyph(target, font_id, item->codepoint, item->x0, item->y0, char_color); draw_font_glyph(target, font_id, item->codepoint, item->x0, item->y0, char_color);
} }
prev_ind = ind; prev_ind = ind;
} }

View File

@ -1,9 +1,9 @@
/* /*
* Mr. 4th Dimention - Allen Webster * Mr. 4th Dimention - Allen Webster
* *
* 12.17.2014 * 10.11.2017
* *
* Rendering layer for project codename "4ed" * Render buffer fill helpers.
* *
*/ */
@ -11,19 +11,19 @@
inline void inline void
draw_push_clip(Render_Target *target, i32_Rect clip_box){ draw_push_clip(Render_Target *target, i32_Rect clip_box){
target->push_clip(target, clip_box); render_push_clip(target, clip_box);
} }
inline i32_Rect inline i32_Rect
draw_pop_clip(Render_Target *target){ draw_pop_clip(Render_Target *target){
i32_Rect result = target->pop_clip(target); i32_Rect result = render_pop_clip(target);
return(result); return(result);
} }
inline void inline void
draw_change_clip(Render_Target *target, i32_Rect clip_box){ draw_change_clip(Render_Target *target, i32_Rect clip_box){
target->pop_clip(target); render_pop_clip(target);
target->push_clip(target, clip_box); render_push_clip(target, clip_box);
} }
internal void internal void
@ -50,7 +50,7 @@ draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){
piece.header.type = piece_type_rectangle; piece.header.type = piece_type_rectangle;
piece.rectangle.rect = f32R(rect); piece.rectangle.rect = f32R(rect);
piece.rectangle.color = color; piece.rectangle.color = color;
target->push_piece(target, piece); render_push_piece(target, piece);
} }
internal void internal void
@ -59,24 +59,7 @@ draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){
piece.header.type = piece_type_rectangle; piece.header.type = piece_type_rectangle;
piece.rectangle.rect = rect; piece.rectangle.rect = rect;
piece.rectangle.color = color; piece.rectangle.color = color;
target->push_piece(target, piece); render_push_piece(target, piece);
}
internal void
draw_gradient_2corner_clipped(Render_Target *target, f32_Rect rect,
Vec4 left_color, Vec4 right_color){
Render_Piece_Combined piece;
piece.header.type = piece_type_gradient;
piece.gradient.rect = rect;
piece.gradient.left_color = pack_color4(left_color);
piece.gradient.right_color = pack_color4(right_color);
target->push_piece(target, piece);
}
inline void
draw_gradient_2corner_clipped(Render_Target *target, f32 l, f32 t, f32 r, f32 b,
Vec4 color_left, Vec4 color_right){
draw_gradient_2corner_clipped(target, f32R(l,t,r,b), color_left, color_right);
} }
internal void internal void
@ -85,7 +68,7 @@ draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){
piece.header.type = piece_type_outline; piece.header.type = piece_type_outline;
piece.rectangle.rect = rect; piece.rectangle.rect = rect;
piece.rectangle.color = color; piece.rectangle.color = color;
target->push_piece(target, piece); render_push_piece(target, piece);
} }
inline void inline void
@ -107,13 +90,8 @@ draw_margin(Render_Target *target, i32_Rect outer, i32 width, u32 color){
draw_margin(target, outer, inner, color); draw_margin(target, outer, inner, color);
} }
inline internal i32
font_predict_size(i32 pt_size){
return pt_size*pt_size*128;
}
internal void internal void
font_draw_glyph(Render_Target *target, Font_ID font_id, i32 type, u32 codepoint, f32 x, f32 y, u32 color){ draw_font_glyph(Render_Target *target, Font_ID font_id, i32 type, u32 codepoint, f32 x, f32 y, u32 color){
Render_Piece_Combined piece; Render_Piece_Combined piece;
piece.header.type = type; piece.header.type = type;
piece.glyph.pos.x = x; piece.glyph.pos.x = x;
@ -121,12 +99,12 @@ font_draw_glyph(Render_Target *target, Font_ID font_id, i32 type, u32 codepoint,
piece.glyph.color = color; piece.glyph.color = color;
piece.glyph.font_id = font_id; piece.glyph.font_id = font_id;
piece.glyph.codepoint = codepoint; piece.glyph.codepoint = codepoint;
target->push_piece(target, piece); render_push_piece(target, piece);
} }
internal void internal void
font_draw_glyph(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){ draw_font_glyph(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){
font_draw_glyph(target, font_id, piece_type_glyph, codepoint, x, y, color); draw_font_glyph(target, font_id, piece_type_glyph, codepoint, x, y, color);
} }
internal f32 internal f32
@ -156,7 +134,7 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i
if (behavior.do_codepoint_advance){ if (behavior.do_codepoint_advance){
u32 codepoint = step.value; u32 codepoint = step.value;
if (color != 0){ if (color != 0){
font_draw_glyph(target, font_id, type, codepoint, x, y, color); draw_font_glyph(target, font_id, type, codepoint, x, y, color);
} }
x += font_get_glyph_advance(system, font, codepoint); x += font_get_glyph_advance(system, font, codepoint);
} }
@ -169,7 +147,7 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i
f32 xx = x; f32 xx = x;
for (u32 j = 0; j < 3; ++j){ for (u32 j = 0; j < 3; ++j){
font_draw_glyph(target, font_id, type, cs[j], xx, y, color); draw_font_glyph(target, font_id, type, cs[j], xx, y, color);
xx += sub_advances[j]; xx += sub_advances[j];
} }
} }
@ -177,54 +155,6 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i
} }
} }
} }
#if 0
for (;str < str_end;){
u8 *byte = str;
u32 codepoint = utf8_to_u32(&str, str_end);
b32 do_codepoint = false;
b32 do_numbers = false;
if (codepoint){
if (codepoint >= ' ' && codepoint <= 0xFF && codepoint != 127){
do_codepoint = true;
}
else{
do_numbers = true;
}
}
else{
do_numbers = true;
}
if (do_codepoint){
if (color != 0){
font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color);
}
x += font_get_glyph_advance(system, font, codepoint);
}
else if (do_numbers){
for (;byte < str; ++byte){
u8_4tech n = *byte;
if (color != 0){
u8 cs[3];
cs[0] = '\\';
byte_to_ascii(n, cs+1);
f32 *advances = font_get_byte_sub_advances(font);
f32 xx = x;
for (u32 j = 0; j < 3; ++j){
font_draw_glyph(target, font_id, type, cs[j], xx, y, color);
xx += advances[j];
}
}
x += byte_advance;
}
}
}
#endif
} }
return(x); return(x);
@ -243,19 +173,6 @@ draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, ch
return(w); return(w);
} }
internal f32
draw_string_mono(System_Functions *system, Render_Target *target, Font_ID font_id, String str, i32 x, i32 y, f32 advance, u32 color){
f32 w = draw_string_base(system, target, font_id, piece_type_mono_glyph, str, x, y, color);
return(w);
}
internal f32
draw_string_mono(System_Functions *system, Render_Target *target, Font_ID font_id, char *str, i32 x, i32 y, f32 advance, u32 color){
String string = make_string_slowly(str);
f32 w = draw_string_base(system, target, font_id, piece_type_mono_glyph, string, x, y, color);
return(w);
}
internal f32 internal f32
font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, String str){ font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, String str){
f32 w = draw_string_base(system, target, font_id, piece_type_glyph, str, 0, 0, 0); f32 w = draw_string_base(system, target, font_id, piece_type_glyph, str, 0, 0, 0);

64
4ed_render_format.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 10.11.2017
*
* Format for 4coder render commands.
*
*/
// TOP
enum Render_Piece_Type{
piece_type_rectangle,
piece_type_outline,
piece_type_glyph,
piece_type_change_clip
};
struct Render_Piece_Header{
i32 type;
};
struct Render_Piece_Rectangle{
f32_Rect rect;
u32 color;
};
struct Render_Piece_Gradient{
f32_Rect rect;
u32 left_color;
u32 right_color;
};
struct Render_Piece_Glyph{
Vec2 pos;
u32 color;
Font_ID font_id;
u32 codepoint;
};
struct Render_Piece_Glyph_Advance{
Vec2 pos;
u32 color;
f32 advance;
Font_ID font_id;
u32 codepoint;
};
struct Render_Piece_Change_Clip{
i32_Rect box;
};
struct Render_Piece_Combined{
Render_Piece_Header header;
union{
Render_Piece_Rectangle rectangle;
Render_Piece_Gradient gradient;
Render_Piece_Glyph glyph;
Render_Piece_Glyph_Advance glyph_advance;
};
};
// BOTTOM

419
4ed_render_opengl.cpp Normal file
View File

@ -0,0 +1,419 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 10.11.2017
*
* OpenGL render implementation
*
*/
// TOP
#define ExtractStruct(s) ((s*)cursor); cursor += sizeof(s)
inline void
private_draw_set_clip(Render_Target *t, i32_Rect clip_box){
glScissor(clip_box.x0, t->height - clip_box.y1, clip_box.x1 - clip_box.x0, clip_box.y1 - clip_box.y0);
}
inline void
private_draw_bind_texture(Render_Target *t, i32 texid){
if (t->bound_texture != texid){
glBindTexture(GL_TEXTURE_2D, texid);
t->bound_texture = texid;
}
}
inline void
private_draw_set_color(Render_Target *t, u32 color){
if (t->color != color){
t->color = color;
Vec4 c = unpack_color4(color);
glColor4f(c.r, c.g, c.b, c.a);
}
}
inline void
private_draw_rectangle(Render_Target *t, f32_Rect rect, u32 color){
private_draw_set_color(t, color);
private_draw_bind_texture(t, 0);
glBegin(GL_QUADS);
{
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
}
inline void
private_draw_rectangle_outline(Render_Target *t, f32_Rect rect, u32 color){
f32_Rect r = get_inner_rect(rect, .5f);
private_draw_set_color(t, color);
private_draw_bind_texture(t, 0);
glBegin(GL_LINE_STRIP);
{
glVertex2f(r.x0, r.y0);
glVertex2f(r.x1, r.y0);
glVertex2f(r.x1, r.y1);
glVertex2f(r.x0, r.y1);
glVertex2f(r.x0, r.y0);
}
glEnd();
}
struct Render_Quad{
f32 x0, y0, x1, y1;
f32 s0, t0, s1, t1;
};
inline Render_Quad
get_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos + b->xoff;
q.y0 = ypos + b->yoff;
q.x1 = xpos + b->xoff2;
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline void
private_draw_glyph(System_Functions *system, Render_Target *t, Render_Font *font, u32 codepoint, f32 x, f32 y, u32 color){
Glyph_Data glyph = font_get_glyph(system, font, codepoint);
if (glyph.tex != 0){
Render_Quad q = get_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
private_draw_set_color(t, color);
private_draw_bind_texture(t, glyph.tex);
glBegin(GL_QUADS);
{
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
}
glEnd();
}
}
internal void
interpret_render_buffer(System_Functions *system, Render_Target *t){
char *cursor = t->push_buffer;
char *cursor_end = cursor + t->size;
for (; cursor < cursor_end;){
Render_Piece_Header *header = ExtractStruct(Render_Piece_Header);
i32 type = header->type;
switch (type){
case piece_type_rectangle:
{
Render_Piece_Rectangle *rectangle = ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle(t, rectangle->rect, rectangle->color);
}break;
case piece_type_outline:
{
Render_Piece_Rectangle *rectangle = ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle_outline(t, rectangle->rect, rectangle->color);
}break;
case piece_type_glyph:
{
Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph);
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
Assert(font != 0);
private_draw_glyph(system, t, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_change_clip:
{
Render_Piece_Change_Clip *clip = ExtractStruct(Render_Piece_Change_Clip);
private_draw_set_clip(t, clip->box);
}break;
}
}
glFlush();
}
#undef ExtractStruct
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
#undef internal
#include <ft2build.h>
#include FT_FREETYPE_H
#define internal static
internal void
font_load_page_inner(Partition *part, Render_Font *font, FT_Library ft, FT_Face face, b32 use_hinting, Glyph_Page *page, u32 page_number, i32 tab_width){
Temp_Memory temp = begin_temp_memory(part);
Assert(page != 0);
page->page_number = page_number;
// prepare to read glyphs into a temporary texture buffer
i32 max_glyph_w = face->size->metrics.x_ppem;
i32 max_glyph_h = font_get_height(font);
i32 tex_width = 64;
i32 tex_height = 0;
do {
tex_width *= 2;
float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w);
float rows = ceilf(ITEM_PER_FONT_PAGE / glyphs_per_row);
tex_height = ceil32(rows * (max_glyph_h + 2));
} while(tex_height > tex_width);
tex_height = round_up_pot_u32(tex_height);
i32 pen_x = 0;
i32 pen_y = 0;
u32* pixels = push_array(part, u32, tex_width * tex_height);
memset(pixels, 0, tex_width * tex_height * sizeof(u32));
u32 ft_flags = FT_LOAD_RENDER;
if (use_hinting){
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
// maybe it could be exposed as an option for hinting, instead of just on/off.
ft_flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
}
else{
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
// fill the texture
u32 base_codepoint = (page_number << 8);
Glyph_Bounds *glyphs = &page->glyphs[0];
Glyph_Bounds *glyph_ptr = glyphs;
f32 *advances = &page->advance[0];
f32 *advance_ptr = advances;
for(u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++glyph_ptr, ++advance_ptr){
u32 codepoint = i + base_codepoint;
if(FT_Load_Char(face, codepoint, ft_flags) == 0){
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
i32 ascent = font_get_ascent(font);
// move to next line if necessary
if(pen_x + w >= tex_width){
pen_x = 0;
pen_y += (max_glyph_h + 2);
}
// set all this stuff the renderer needs
glyph_ptr->x0 = (f32)(pen_x);
glyph_ptr->y0 = (f32)(pen_y);
glyph_ptr->x1 = (f32)(pen_x + w);
glyph_ptr->y1 = (f32)(pen_y + h + 1);
glyph_ptr->xoff = (f32)(face->glyph->bitmap_left);
glyph_ptr->yoff = (f32)(ascent - face->glyph->bitmap_top);
glyph_ptr->xoff2 = glyph_ptr->xoff + w;
glyph_ptr->yoff2 = glyph_ptr->yoff + h + 1;
// TODO(allen): maybe advance data should be integers?
*advance_ptr = (f32)ceil32(face->glyph->advance.x / 64.0f);
// write to texture atlas
i32 pitch = face->glyph->bitmap.pitch;
for(i32 Y = 0; Y < h; ++Y){
for(i32 X = 0; X < w; ++X){
i32 x = pen_x + X;
i32 y = pen_y + Y;
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[Y * pitch + X] * 0x01010101;
}
}
pen_x = ceil32(glyph_ptr->x1 + 1);
}
}
// upload texture
tex_height = round_up_pot_u32(pen_y + max_glyph_h + 2);
page->tex_width = tex_width;
page->tex_height = tex_height;
glGenTextures(1, &page->tex);
glBindTexture(GL_TEXTURE_2D, page->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
end_temp_memory(temp);
// whitespace spacing stuff
if (page_number == 0){
f32 space_adv = advances[' '];
f32 backslash_adv = advances['\\'];
f32 r_adv = advances['r'];
advances['\n'] = space_adv;
advances['\r'] = backslash_adv + r_adv;
advances['\t'] = space_adv*tab_width;
}
}
internal b32
font_load_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
char *filename = font->filename;
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
// NOTE(allen): set texture and glyph data.
font_load_page_inner(part, font, ft, face, use_hinting, page, page_number, 4);
FT_Done_FreeType(ft);
return(true);
}
internal b32
font_load(System_Functions *system, Partition *part, Render_Font *font, i32 pt_size, b32 use_hinting){
char *filename = font->filename;
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
// set size & metrics
char *name = face->family_name;
u32 name_len = 0;
for (;name[name_len];++name_len);
name_len = clamp_top(name_len, sizeof(font->name)-1);
memcpy(font->name, name, name_len);
font->name[name_len] = 0;
font->name_len = name_len;
font->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
font->descent = floor32 (face->size->metrics.descender / 64.0f);
font->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
font->height = ceil32 (face->size->metrics.height / 64.0f);
font->line_skip = font->height - (font->ascent - font->descent);
font->height -= font->line_skip;
font->line_skip = 0;
// NOTE(allen): set texture and glyph data.
Glyph_Page *page = font_get_or_make_page(system, font, 0);
// NOTE(allen): Setup some basic spacing stuff.
f32 backslash_adv = page->advance['\\'];
f32 max_hex_advance = 0.f;
for (u32 i = '0'; i <= '9'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'a'; i <= 'f'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
font->byte_advance = backslash_adv + max_hex_advance*2;
font->byte_sub_advances[0] = backslash_adv;
font->byte_sub_advances[1] = max_hex_advance;
font->byte_sub_advances[2] = max_hex_advance;
FT_Done_FreeType(ft);
return(true);
}
internal void
system_set_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
Assert(pt_size >= 8);
memset(page, 0, sizeof(*page));
if (part->base == 0){
*part = sysshared_scratch_partition(MB(8));
}
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = font_load_page(system, part, font, page, page_number, pt_size, use_hinting);
if (success){
break;
}
else{
sysshared_partition_double(part);
}
}
}
internal void
system_set_font(System_Functions *system, Partition *part, Render_Font *font, char *filename, u32 pt_size, b32 use_hinting){
memset(font, 0, sizeof(*font));
u32 filename_len = 0;
for (;filename[filename_len];++filename_len);
if (filename_len <= sizeof(font->filename)-1){
memcpy(font->filename, filename, filename_len);
font->filename[filename_len] = 0;
font->filename_len = filename_len;
if (part->base == 0){
*part = sysshared_scratch_partition(MB(8));
}
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = font_load(system, part, font, pt_size, use_hinting);
if (success){
break;
}
else{
sysshared_partition_double(part);
}
}
}
}
// BOTTOM

86
4ed_render_target.cpp Normal file
View File

@ -0,0 +1,86 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 10.11.2017
*
* Render target function implementations.
*
*/
// TOP
#define Render_Push_Clip_Sig(n, t, c) void (n)(Render_Target *t, i32_Rect c)
#define Render_Pop_Clip_Sig(n, t) i32_Rect (n)(Render_Target *t)
#define Render_Push_Piece_Sig(n, t, p) void (n)(Render_Target *t, Render_Piece_Combined p)
inline void
draw_safe_push(Render_Target *t, i32 size, void *x){
if (size + t->size <= t->max){
memcpy(t->push_buffer + t->size, x, size);
t->size += size;
}
}
#define PutStruct(s,x) draw_safe_push(t, sizeof(s), &x)
internal
Render_Push_Piece_Sig(render_push_piece, t, piece){
if (!t->clip_all){
PutStruct(Render_Piece_Header, piece.header);
switch (piece.header.type){
case piece_type_rectangle: case piece_type_outline:
{
PutStruct(Render_Piece_Rectangle, piece.rectangle);
}break;
case piece_type_glyph:
{
PutStruct(Render_Piece_Glyph, piece.glyph);
}break;
}
Assert(t->size <= t->max);
}
}
internal void
render_push_piece_clip(Render_Target *t, i32_Rect clip_box){
if (!t->clip_all){
// TODO(allen): optimize out if there are two clip box changes in a row
Render_Piece_Change_Clip clip = {0};
Render_Piece_Header header = {0};
header.type = piece_type_change_clip;
clip.box = clip_box;
PutStruct(Render_Piece_Header, header);
PutStruct(Render_Piece_Change_Clip, clip);
}
}
internal
Render_Push_Clip_Sig(render_push_clip, t, clip_box){
Assert(t->clip_top == -1 || fits_inside(clip_box, t->clip_boxes[t->clip_top]));
Assert(t->clip_top+1 < ArrayCount(t->clip_boxes));
t->clip_boxes[++t->clip_top] = clip_box;
t->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
render_push_piece_clip(t, clip_box);
}
internal
Render_Pop_Clip_Sig(render_pop_clip, t){
Assert(t->clip_top > 0);
i32_Rect result = t->clip_boxes[t->clip_top];
--t->clip_top;
i32_Rect clip_box = t->clip_boxes[t->clip_top];
t->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
render_push_piece_clip(t, clip_box);
return(result);
}
// BOTTOM

33
4ed_render_target.h Normal file
View File

@ -0,0 +1,33 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 10.11.2017
*
* Render target type definition
*
*/
// TOP
#if !defined(FRED_RENDER_TARGET_H)
#define FRED_RENDER_TARGET_H
struct Render_Target{
void *handle;
void *context;
i32_Rect clip_boxes[5];
i32 clip_top;
b32 clip_all;
i32 width, height;
i32 bound_texture;
u32 color;
// TODO(allen): change this to a Partition
char *push_buffer;
i32 size, max;
};
#endif
// BOTTOM

View File

@ -1,122 +0,0 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 17.12.2014
*
* Rendering layer for project codename "4ed"
*
*/
// TOP
#ifndef FRED_RENDERING_H
#define FRED_RENDERING_H
//
// Render Commands
//
enum Render_Piece_Type{
piece_type_rectangle,
piece_type_outline,
piece_type_gradient,
piece_type_glyph,
piece_type_mono_glyph,
piece_type_mono_glyph_advance,
piece_type_change_clip
};
struct Render_Piece_Header{
i32 type;
};
struct Render_Piece_Rectangle{
f32_Rect rect;
u32 color;
};
struct Render_Piece_Gradient{
f32_Rect rect;
u32 left_color;
u32 right_color;
};
struct Render_Piece_Glyph{
Vec2 pos;
u32 color;
Font_ID font_id;
u32 codepoint;
};
struct Render_Piece_Glyph_Advance{
Vec2 pos;
u32 color;
f32 advance;
Font_ID font_id;
u32 codepoint;
};
struct Render_Piece_Change_Clip{
i32_Rect box;
};
struct Render_Piece_Combined{
Render_Piece_Header header;
union{
Render_Piece_Rectangle rectangle;
Render_Piece_Gradient gradient;
Render_Piece_Glyph glyph;
Render_Piece_Glyph_Advance glyph_advance;
};
};
struct Render_Target;
#define Draw_Push_Clip_Sig(name) void name(Render_Target *target, i32_Rect clip_box)
typedef Draw_Push_Clip_Sig(Draw_Push_Clip);
#define Draw_Pop_Clip_Sig(name) i32_Rect name(Render_Target *target)
typedef Draw_Pop_Clip_Sig(Draw_Pop_Clip);
#define Draw_Push_Piece_Sig(name) void name(Render_Target *target, Render_Piece_Combined piece)
typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
//
// Render target stuff
//
struct Render_Target{
void *handle;
void *context;
i32_Rect clip_boxes[5];
i32 clip_top;
b32 clip_all;
i32 width, height;
i32 bound_texture;
u32 color;
// TODO(allen): change this to a Partition
char *push_buffer;
i32 size, max;
Draw_Push_Clip *push_clip;
Draw_Pop_Clip *pop_clip;
Draw_Push_Piece *push_piece;
};
#define DpiMultiplier(n,dpi) ((n) * (dpi) / 96)
inline i32_Rect
rect_from_target(Render_Target *target){
i32_Rect r;
r.x0 = 0;
r.y0 = 0;
r.x1 = target->width;
r.y1 = target->height;
return(r);
}
#endif
// BOTTOM

View File

@ -222,598 +222,6 @@ sysshared_to_binary_path(String *out_filename, char *filename){
return(translate_success); return(translate_success);
} }
//
// Rendering Interface
//
inline void
draw_safe_push(Render_Target *t, i32 size, void *x){
if (size + t->size <= t->max){
memcpy(t->push_buffer + t->size, x, size);
t->size += size;
}
}
#define PutStruct(s,x) draw_safe_push(t, sizeof(s), &x)
internal void
draw_push_piece(Render_Target *t, Render_Piece_Combined piece){
if (!t->clip_all){
PutStruct(Render_Piece_Header, piece.header);
switch (piece.header.type){
case piece_type_rectangle: case piece_type_outline:
{
PutStruct(Render_Piece_Rectangle, piece.rectangle);
}break;
case piece_type_gradient:
{
PutStruct(Render_Piece_Gradient, piece.gradient);
}break;
case piece_type_glyph: case piece_type_mono_glyph:
{
PutStruct(Render_Piece_Glyph, piece.glyph);
}break;
case piece_type_mono_glyph_advance:
{
PutStruct(Render_Piece_Glyph_Advance, piece.glyph_advance);
}break;
}
Assert(t->size <= t->max);
}
}
internal void
draw_push_piece_clip(Render_Target *t, i32_Rect clip_box){
if (!t->clip_all){
// TODO(allen): optimize out if there are two clip box changes in a row
Render_Piece_Change_Clip clip;
Render_Piece_Header header;
header.type = piece_type_change_clip;
clip.box = clip_box;
PutStruct(Render_Piece_Header, header);
PutStruct(Render_Piece_Change_Clip, clip);
}
}
internal void
draw_push_clip(Render_Target *t, i32_Rect clip_box){
Assert(t->clip_top == -1 || fits_inside(clip_box, t->clip_boxes[t->clip_top]));
Assert(t->clip_top+1 < ArrayCount(t->clip_boxes));
t->clip_boxes[++t->clip_top] = clip_box;
t->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
draw_push_piece_clip(t, clip_box);
}
internal i32_Rect
draw_pop_clip(Render_Target *t){
Assert(t->clip_top > 0);
i32_Rect result = t->clip_boxes[t->clip_top];
--t->clip_top;
i32_Rect clip_box = t->clip_boxes[t->clip_top];
t->clip_all = (clip_box.x0 >= clip_box.x1 || clip_box.y0 >= clip_box.y1);
draw_push_piece_clip(t, clip_box);
return(result);
}
internal void
link_rendering(){
target.push_clip = draw_push_clip;
target.pop_clip = draw_pop_clip;
target.push_piece = draw_push_piece;
}
//
// OpenGL
//
#define ExtractStruct(s) ((s*)cursor); cursor += sizeof(s)
inline void
draw_set_clip(Render_Target *t, i32_Rect clip_box){
glScissor(clip_box.x0, t->height - clip_box.y1, clip_box.x1 - clip_box.x0, clip_box.y1 - clip_box.y0);
}
inline void
draw_bind_texture(Render_Target *t, i32 texid){
if (t->bound_texture != texid){
glBindTexture(GL_TEXTURE_2D, texid);
t->bound_texture = texid;
}
}
inline void
draw_set_color(Render_Target *t, u32 color){
if (t->color != color){
t->color = color;
Vec4 c = unpack_color4(color);
glColor4f(c.r, c.g, c.b, c.a);
}
}
inline void
private_draw_rectangle(Render_Target *t, f32_Rect rect, u32 color){
draw_set_color(t, color);
draw_bind_texture(t, 0);
glBegin(GL_QUADS);
{
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
}
inline void
private_draw_rectangle_outline(Render_Target *t, f32_Rect rect, u32 color){
f32_Rect r = get_inner_rect(rect, .5f);
draw_set_color(t, color);
draw_bind_texture(t, 0);
glBegin(GL_LINE_STRIP);
{
glVertex2f(r.x0, r.y0);
glVertex2f(r.x1, r.y0);
glVertex2f(r.x1, r.y1);
glVertex2f(r.x0, r.y1);
glVertex2f(r.x0, r.y0);
}
glEnd();
}
inline void
private_draw_gradient(Render_Target *t, f32_Rect rect, Vec4 color_left, Vec4 color_right){
Vec4 cl = color_left;
Vec4 cr = color_right;
draw_bind_texture(t, 0);
glBegin(GL_QUADS);
{
glColor4f(cl.r, cl.g, cl.b, cl.a);
glVertex2f(rect.x0, rect.y0);
glVertex2f(rect.x0, rect.y1);
glColor4f(cr.r, cr.g, cr.b, cr.a);
glVertex2f(rect.x1, rect.y1);
glVertex2f(rect.x1, rect.y0);
}
glEnd();
}
struct Render_Quad{
f32 x0, y0, x1, y1;
f32 s0, t0, s1, t1;
};
inline Render_Quad
get_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos + b->xoff;
q.y0 = ypos + b->yoff;
q.x1 = xpos + b->xoff2;
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline Render_Quad
get_exact_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
Render_Quad q;
float ipw = 1.0f / pw, iph = 1.0f / ph;
q.x0 = xpos;
q.y0 = ypos + b->yoff;
q.x1 = xpos + (b->xoff2 - b->xoff);
q.y1 = ypos + b->yoff2;
q.s0 = b->x0 * ipw;
q.t0 = b->y0 * iph;
q.s1 = b->x1 * ipw;
q.t1 = b->y1 * iph;
return(q);
}
inline void
private_draw_glyph(System_Functions *system, Render_Target *t, Render_Font *font, u32 codepoint, f32 x, f32 y, u32 color){
Glyph_Data glyph = font_get_glyph(system, font, codepoint);
if (glyph.tex != 0){
Render_Quad q = get_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
draw_set_color(t, color);
draw_bind_texture(t, glyph.tex);
glBegin(GL_QUADS);
{
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
}
glEnd();
}
}
inline void
private_draw_glyph_mono(System_Functions *system, Render_Target *t, Render_Font *font, u32 codepoint, f32 x, f32 y, f32 advance, u32 color){
Glyph_Data glyph = font_get_glyph(system, font, codepoint);
if (glyph.tex != 0){
f32 left = glyph.bounds.x0;
f32 right = glyph.bounds.x1;
f32 width = (right - left);
f32 x_shift = (advance - width) * .5f;
x += x_shift;
Render_Quad q = get_exact_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
draw_set_color(t, color);
draw_bind_texture(t, glyph.tex);
glBegin(GL_QUADS);
{
glTexCoord2f(q.s0, q.t1); glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1); glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0); glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0); glVertex2f(q.x0, q.y0);
}
glEnd();
}
}
inline void
private_draw_glyph_mono(System_Functions *system, Render_Target *t, Render_Font *font, u32 character, f32 x, f32 y, u32 color){
f32 advance = (f32)font_get_advance(font);
private_draw_glyph_mono(system, t, font, character, x, y, advance, color);
}
internal void
launch_rendering(System_Functions *system, Render_Target *t){
char *cursor = t->push_buffer;
char *cursor_end = cursor + t->size;
for (; cursor < cursor_end;){
Render_Piece_Header *header = ExtractStruct(Render_Piece_Header);
i32 type = header->type;
switch (type){
case piece_type_rectangle:
{
Render_Piece_Rectangle *rectangle = ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle(t, rectangle->rect, rectangle->color);
}break;
case piece_type_outline:
{
Render_Piece_Rectangle *rectangle = ExtractStruct(Render_Piece_Rectangle);
private_draw_rectangle_outline(t, rectangle->rect, rectangle->color);
}break;
case piece_type_gradient:
{
Render_Piece_Gradient *gradient = ExtractStruct(Render_Piece_Gradient);
private_draw_gradient(t, gradient->rect, unpack_color4(gradient->left_color), unpack_color4(gradient->right_color));
}break;
case piece_type_glyph:
{
Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph);
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
Assert(font != 0);
private_draw_glyph(system, t, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph:
{
Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph);
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
Assert(font != 0);
private_draw_glyph_mono(system, t, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->color);
}break;
case piece_type_mono_glyph_advance:
{
Render_Piece_Glyph_Advance *glyph = ExtractStruct(Render_Piece_Glyph_Advance);
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
Assert(font != 0);
private_draw_glyph_mono(system, t, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->advance, glyph->color);
}break;
case piece_type_change_clip:
{
Render_Piece_Change_Clip *clip = ExtractStruct(Render_Piece_Change_Clip);
draw_set_clip(t, clip->box);
}break;
}
}
}
#undef ExtractStruct
// NOTE(allen): Thanks to insofaras. This is copy-pasted from some work he originally did to get free type working on Linux.
#undef internal
#include <ft2build.h>
#include FT_FREETYPE_H
#define internal static
internal void
font_load_page_inner(Partition *part, Render_Font *font, FT_Library ft, FT_Face face, b32 use_hinting, Glyph_Page *page, u32 page_number, i32 tab_width){
Temp_Memory temp = begin_temp_memory(part);
Assert(page != 0);
page->page_number = page_number;
// prepare to read glyphs into a temporary texture buffer
i32 max_glyph_w = face->size->metrics.x_ppem;
i32 max_glyph_h = font_get_height(font);
i32 tex_width = 64;
i32 tex_height = 0;
do {
tex_width *= 2;
float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w);
float rows = ceilf(ITEM_PER_FONT_PAGE / glyphs_per_row);
tex_height = ceil32(rows * (max_glyph_h + 2));
} while(tex_height > tex_width);
tex_height = round_up_pot_u32(tex_height);
i32 pen_x = 0;
i32 pen_y = 0;
u32* pixels = push_array(part, u32, tex_width * tex_height);
memset(pixels, 0, tex_width * tex_height * sizeof(u32));
u32 ft_flags = FT_LOAD_RENDER;
if (use_hinting){
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
// maybe it could be exposed as an option for hinting, instead of just on/off.
ft_flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
}
else{
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
}
// fill the texture
u32 base_codepoint = (page_number << 8);
Glyph_Bounds *glyphs = &page->glyphs[0];
Glyph_Bounds *glyph_ptr = glyphs;
f32 *advances = &page->advance[0];
f32 *advance_ptr = advances;
for(u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++glyph_ptr, ++advance_ptr){
u32 codepoint = i + base_codepoint;
if(FT_Load_Char(face, codepoint, ft_flags) == 0){
i32 w = face->glyph->bitmap.width;
i32 h = face->glyph->bitmap.rows;
i32 ascent = font_get_ascent(font);
// move to next line if necessary
if(pen_x + w >= tex_width){
pen_x = 0;
pen_y += (max_glyph_h + 2);
}
// set all this stuff the renderer needs
glyph_ptr->x0 = (f32)(pen_x);
glyph_ptr->y0 = (f32)(pen_y);
glyph_ptr->x1 = (f32)(pen_x + w);
glyph_ptr->y1 = (f32)(pen_y + h + 1);
glyph_ptr->xoff = (f32)(face->glyph->bitmap_left);
glyph_ptr->yoff = (f32)(ascent - face->glyph->bitmap_top);
glyph_ptr->xoff2 = glyph_ptr->xoff + w;
glyph_ptr->yoff2 = glyph_ptr->yoff + h + 1;
// TODO(allen): maybe advance data should be integers?
*advance_ptr = (f32)ceil32(face->glyph->advance.x / 64.0f);
// write to texture atlas
i32 pitch = face->glyph->bitmap.pitch;
for(i32 Y = 0; Y < h; ++Y){
for(i32 X = 0; X < w; ++X){
i32 x = pen_x + X;
i32 y = pen_y + Y;
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[Y * pitch + X] * 0x01010101;
}
}
pen_x = ceil32(glyph_ptr->x1 + 1);
}
}
// upload texture
tex_height = round_up_pot_u32(pen_y + max_glyph_h + 2);
page->tex_width = tex_width;
page->tex_height = tex_height;
glGenTextures(1, &page->tex);
glBindTexture(GL_TEXTURE_2D, page->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
end_temp_memory(temp);
// whitespace spacing stuff
if (page_number == 0){
f32 space_adv = advances[' '];
f32 backslash_adv = advances['\\'];
f32 r_adv = advances['r'];
advances['\n'] = space_adv;
advances['\r'] = backslash_adv + r_adv;
advances['\t'] = space_adv*tab_width;
}
}
internal b32
font_load_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
char *filename = font->filename;
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
// NOTE(allen): set texture and glyph data.
font_load_page_inner(part, font, ft, face, use_hinting, page, page_number, 4);
FT_Done_FreeType(ft);
return(true);
}
internal b32
font_load(System_Functions *system, Partition *part, Render_Font *font, i32 pt_size, b32 use_hinting){
char *filename = font->filename;
// TODO(allen): Stop redoing all this init for each call.
FT_Library ft;
FT_Init_FreeType(&ft);
FT_Face face;
FT_New_Face(ft, filename, 0, &face);
FT_Size_RequestRec_ size = {};
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
size.height = pt_size << 6;
FT_Request_Size(face, &size);
// set size & metrics
char *name = face->family_name;
u32 name_len = 0;
for (;name[name_len];++name_len);
name_len = clamp_top(name_len, sizeof(font->name)-1);
memcpy(font->name, name, name_len);
font->name[name_len] = 0;
font->name_len = name_len;
font->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
font->descent = floor32 (face->size->metrics.descender / 64.0f);
font->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
font->height = ceil32 (face->size->metrics.height / 64.0f);
font->line_skip = font->height - (font->ascent - font->descent);
font->height -= font->line_skip;
font->line_skip = 0;
// NOTE(allen): set texture and glyph data.
Glyph_Page *page = font_get_or_make_page(system, font, 0);
// NOTE(allen): Setup some basic spacing stuff.
f32 backslash_adv = page->advance['\\'];
f32 max_hex_advance = 0.f;
for (u32 i = '0'; i <= '9'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'a'; i <= 'f'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
for (u32 i = 'A'; i <= 'F'; ++i){
f32 adv = page->advance[i];
max_hex_advance = Max(max_hex_advance, adv);
}
font->byte_advance = backslash_adv + max_hex_advance*2;
font->byte_sub_advances[0] = backslash_adv;
font->byte_sub_advances[1] = max_hex_advance;
font->byte_sub_advances[2] = max_hex_advance;
FT_Done_FreeType(ft);
return(true);
}
internal void
system_set_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
Assert(pt_size >= 8);
memset(page, 0, sizeof(*page));
if (part->base == 0){
*part = sysshared_scratch_partition(MB(8));
}
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = font_load_page(system, part, font, page, page_number, pt_size, use_hinting);
if (success){
break;
}
else{
sysshared_partition_double(part);
}
}
}
internal void
system_set_font(System_Functions *system, Partition *part, Render_Font *font, char *filename, u32 pt_size, b32 use_hinting){
memset(font, 0, sizeof(*font));
u32 filename_len = 0;
for (;filename[filename_len];++filename_len);
if (filename_len <= sizeof(font->filename)-1){
memcpy(font->filename, filename, filename_len);
font->filename[filename_len] = 0;
font->filename_len = filename_len;
if (part->base == 0){
*part = sysshared_scratch_partition(MB(8));
}
b32 success = false;
for (u32 R = 0; R < 3; ++R){
success = font_load(system, part, font, pt_size, use_hinting);
if (success){
break;
}
else{
sysshared_partition_double(part);
}
}
}
}
#endif #endif
// BOTTOM // BOTTOM

View File

@ -38,7 +38,8 @@
#include "4ed_system.h" #include "4ed_system.h"
#include "4ed_log.h" #include "4ed_log.h"
#include "4ed_rendering.h" #include "4ed_render_format.h"
#include "4ed_render_target.h"
#include "4ed.h" #include "4ed.h"
#include "4ed_file_track.h" #include "4ed_file_track.h"
@ -431,15 +432,14 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
int status; int status;
if (pid && waitpid(pid, &status, WNOHANG) > 0){ if (pid && waitpid(pid, &status, WNOHANG) > 0){
close_me = true;
cli->exit = WEXITSTATUS(status); cli->exit = WEXITSTATUS(status);
close_me = true;
close(*(int*)&cli->out_read);
close(*(int*)&cli->out_write);
struct epoll_event e = {}; struct epoll_event e = {};
epoll_ctl(linuxvars.epoll, EPOLL_CTL_DEL, *(int*)&cli->out_read, &e); epoll_ctl(linuxvars.epoll, EPOLL_CTL_DEL, *(int*)&cli->out_read, &e);
close(*(int*)&cli->out_read);
close(*(int*)&cli->out_write);
} }
return(close_me); return(close_me);
@ -447,6 +447,7 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
#include "4ed_font_data.h" #include "4ed_font_data.h"
#include "4ed_system_shared.cpp" #include "4ed_system_shared.cpp"
#include "4ed_render_opengl.cpp"
// //
// End of system funcs // End of system funcs
@ -456,13 +457,6 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
// Renderer // Renderer
// //
internal void
LinuxRedrawTarget(){
launch_rendering(&sysfunc, &target);
//glFlush();
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
}
internal void internal void
LinuxResizeTarget(i32 width, i32 height){ LinuxResizeTarget(i32 width, i32 height){
if (width > 0 && height > 0){ if (width > 0 && height > 0){
@ -1564,7 +1558,6 @@ main(int argc, char **argv){
// //
load_app_code(); load_app_code();
link_rendering();
#if defined(FRED_SUPER) #if defined(FRED_SUPER)
load_custom_code(); load_custom_code();
#else #else
@ -1840,7 +1833,8 @@ main(int argc, char **argv){
system_schedule_step(); system_schedule_step();
} }
LinuxRedrawTarget(); interpret_render_buffer(&sysfunc, &target);
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
if (result.mouse_cursor_type != linuxvars.cursor && !linuxvars.input.mouse.l){ if (result.mouse_cursor_type != linuxvars.cursor && !linuxvars.input.mouse.l){
Cursor c = xcursors[result.mouse_cursor_type]; Cursor c = xcursors[result.mouse_cursor_type];

View File

@ -37,7 +37,8 @@
#include "4ed_system.h" #include "4ed_system.h"
#include "4ed_log.h" #include "4ed_log.h"
#include "4ed_rendering.h" #include "4ed_render_format.h"
#include "4ed_render_target.h"
#include "4ed.h" #include "4ed.h"
#include "4ed_file_track.h" #include "4ed_file_track.h"
@ -311,6 +312,7 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
#include "4ed_font_data.h" #include "4ed_font_data.h"
#include "4ed_system_shared.cpp" #include "4ed_system_shared.cpp"
#include "4ed_render_opengl.cpp"
//////////////////////////////// ////////////////////////////////
@ -539,7 +541,7 @@ osx_step(void){
osx_show_cursor(0, result.mouse_cursor_type); osx_show_cursor(0, result.mouse_cursor_type);
launch_rendering(&sysfunc, &target); interpret_render_buffer(&sysfunc, &target);
if (result.animating || cli_count > 0){ if (result.animating || cli_count > 0){
osx_schedule_step(); osx_schedule_step();
@ -609,7 +611,6 @@ osx_init(){
DBG_POINT(); DBG_POINT();
load_app_code(); load_app_code();
link_rendering();
#if defined(FRED_SUPER) #if defined(FRED_SUPER)
load_custom_code(); load_custom_code();
#else #else

View File

@ -48,7 +48,8 @@
#include "4ed_system.h" #include "4ed_system.h"
#include "4ed_log.h" #include "4ed_log.h"
#include "4ed_rendering.h" #include "4ed_render_format.h"
#include "4ed_render_target.h"
#include "4ed.h" #include "4ed.h"
#include <Windows.h> #include <Windows.h>
@ -448,7 +449,7 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){
internal internal
Sys_CLI_End_Update_Sig(system_cli_end_update){ Sys_CLI_End_Update_Sig(system_cli_end_update){
b32 close_me = 0; b32 close_me = false;
HANDLE proc = *(HANDLE*)&cli->proc; HANDLE proc = *(HANDLE*)&cli->proc;
DWORD result = 0; DWORD result = 0;
@ -460,22 +461,20 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
cli->exit = (i32)result; cli->exit = (i32)result;
} }
close_me = 1; close_me = true;
CloseHandle(*(HANDLE*)&cli->proc); CloseHandle(*(HANDLE*)&cli->proc);
CloseHandle(*(HANDLE*)&cli->out_read); CloseHandle(*(HANDLE*)&cli->out_read);
CloseHandle(*(HANDLE*)&cli->out_write); CloseHandle(*(HANDLE*)&cli->out_write);
--win32vars.running_cli; --win32vars.running_cli;
} }
return(close_me); return(close_me);
} }
//
// Linkage to Custom and Application
//
#include "4ed_font_data.h" #include "4ed_font_data.h"
#include "4ed_system_shared.cpp" #include "4ed_system_shared.cpp"
#include "4ed_render_opengl.cpp"
// //
// Helpers // Helpers
@ -517,13 +516,6 @@ Win32KeycodeInit(){
keycode_lookup_table[VK_F16] = key_f16; keycode_lookup_table[VK_F16] = key_f16;
} }
internal void
Win32RedrawScreen(HDC hdc){
launch_rendering(&sysfunc, &target);
glFlush();
SwapBuffers(hdc);
}
internal void internal void
Win32Resize(i32 width, i32 height){ Win32Resize(i32 width, i32 height){
if (width > 0 && height > 0){ if (width > 0 && height > 0){
@ -932,7 +924,8 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
win32vars.got_useful_event = true; win32vars.got_useful_event = true;
PAINTSTRUCT ps; PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps); HDC hdc = BeginPaint(hwnd, &ps);
Win32RedrawScreen(hdc); // NOTE(allen): Do nothing?
AllowLocal(hdc);
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
}break; }break;
@ -948,11 +941,6 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
win32vars.got_useful_event = true; win32vars.got_useful_event = true;
}break; }break;
case WM_CANCELMODE:
{
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
}break;
default: default:
{ {
result = DefWindowProc(hwnd, uMsg, wParam, lParam); result = DefWindowProc(hwnd, uMsg, wParam, lParam);
@ -1006,7 +994,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
// //
load_app_code(); load_app_code();
link_rendering();
#if defined(FRED_SUPER) #if defined(FRED_SUPER)
load_custom_code(); load_custom_code();
#else #else
@ -1396,7 +1383,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
win32vars.lctrl_lalt_is_altgr = result.lctrl_lalt_is_altgr; win32vars.lctrl_lalt_is_altgr = result.lctrl_lalt_is_altgr;
HDC hdc = GetDC(win32vars.window_handle); HDC hdc = GetDC(win32vars.window_handle);
Win32RedrawScreen(hdc); interpret_render_buffer(&sysfunc, &target);
SwapBuffers(hdc);
ReleaseDC(win32vars.window_handle, hdc); ReleaseDC(win32vars.window_handle, hdc);
win32vars.first = 0; win32vars.first = 0;

View File

@ -1283,7 +1283,12 @@ replace_range_str(String *str, i32_4tech first, i32_4tech one_past_last, String
CPP_NAME(replace_str) CPP_NAME(replace_str)
API_EXPORT FSTRING_LINK void API_EXPORT FSTRING_LINK void
replace_str_ss(String *str, String replace, String with){ replace_str_ss(String *str, String replace, String with)/*
DOC_PARAM(str, The string to modify.)
DOC_PARAM(replace, A string matching the zero or more substring to be replaced within str.)
DOC_PARAM(with, The string to be placed into str in place of occurrences of replace.)
DOC(Modifies str so that every occurence of replace that was within str is gone and the string in with has taken their places.)
*/{
i32_4tech i = 0; i32_4tech i = 0;
for (;;){ for (;;){
i = find_substr_s(*str, i, replace); i = find_substr_s(*str, i, replace);
@ -1297,21 +1302,36 @@ replace_str_ss(String *str, String replace, String with){
CPP_NAME(replace_str) CPP_NAME(replace_str)
API_EXPORT FSTRING_LINK void API_EXPORT FSTRING_LINK void
replace_str_sc(String *str, String replace, char *with){ replace_str_sc(String *str, String replace, char *with)/*
DOC_PARAM(str, The string to modify.)
DOC_PARAM(replace, A string matching the zero or more substring to be replaced within str. Must be null terminated, and will be counted, it is always faster to use a String parameter here when possible.)
DOC_PARAM(with, The string to be placed into str in place of occurrences of replace.)
DOC(Modifies str so that every occurence of replace that was within str is gone and the string in with has taken their places.)
*/{
String w = make_string_slowly(with); String w = make_string_slowly(with);
replace_str_ss(str, replace, w); replace_str_ss(str, replace, w);
} }
CPP_NAME(replace_str) CPP_NAME(replace_str)
API_EXPORT FSTRING_LINK void API_EXPORT FSTRING_LINK void
replace_str_cs(String *str, char *replace, String with){ replace_str_cs(String *str, char *replace, String with)/*
DOC_PARAM(str, The string to modify.)
DOC_PARAM(replace, A string matching the zero or more substring to be replaced within str.)
DOC_PARAM(with, The string to be placed into str in place of occurrences of replace. Must be null terminated, and will be counted, it is always faster to use a String parameter here when possible.)
DOC(Modifies str so that every occurence of replace that was within str is gone and the string in with has taken their places.)
*/{
String r = make_string_slowly(replace); String r = make_string_slowly(replace);
replace_str_ss(str, r, with); replace_str_ss(str, r, with);
} }
CPP_NAME(replace_str) CPP_NAME(replace_str)
API_EXPORT FSTRING_LINK void API_EXPORT FSTRING_LINK void
replace_str_cc(String *str, char *replace, char *with){ replace_str_cc(String *str, char *replace, char *with)/*
DOC_PARAM(str, The string to modify.)
DOC_PARAM(replace, A string matching the zero or more substring to be replaced within str. Must be null terminated, and will be counted, it is always faster to use a String parameter here when possible.)
DOC_PARAM(with, The string to be placed into str in place of occurrences of replace. Must be null terminated, and will be counted, it is always faster to use a String parameter here when possible.)
DOC(Modifies str so that every occurence of replace that was within str is gone and the string in with has taken their places.)
*/{
String r = make_string_slowly(replace); String r = make_string_slowly(replace);
String w = make_string_slowly(with); String w = make_string_slowly(with);
replace_str_ss(str, r, w); replace_str_ss(str, r, w);