From c0bf8966eb855c23f32b7493eecef8313764d4d9 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Fri, 10 Nov 2017 13:27:39 -0500 Subject: [PATCH] cleaning up opengl code --- 4ed.cpp | 7 +- 4ed_app_target.cpp | 8 +- 4ed_file_view.cpp | 2 +- ...endering_helper.cpp => 4ed_render_fill.cpp | 113 +--- 4ed_render_format.h | 64 ++ 4ed_render_opengl.cpp | 419 +++++++++++++ 4ed_render_target.cpp | 86 +++ 4ed_render_target.h | 33 + 4ed_rendering.h | 122 ---- platform_all/4ed_system_shared.cpp | 592 ------------------ platform_linux/linux_4ed.cpp | 24 +- platform_mac/mac_4ed.cpp | 7 +- platform_win32/win32_4ed.cpp | 32 +- string/internal_4coder_string.cpp | 28 +- 14 files changed, 676 insertions(+), 861 deletions(-) rename 4ed_rendering_helper.cpp => 4ed_render_fill.cpp (59%) create mode 100644 4ed_render_format.h create mode 100644 4ed_render_opengl.cpp create mode 100644 4ed_render_target.cpp create mode 100644 4ed_render_target.h delete mode 100644 4ed_rendering.h diff --git a/4ed.cpp b/4ed.cpp index 59cd34e1..b3decb21 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -2313,7 +2313,12 @@ App_Step_Sig(app_step){ begin_render_section(target, system); 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; USE_PANEL(active_panel); diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index bef8ba68..a75ee39d 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -19,7 +19,6 @@ #include "4ed_math.h" #include "4ed_system.h" -// TODO(allen): set in compilation line #define PREFERRED_ALIGNMENT 8 #define USE_DEBUG_MEMORY @@ -33,7 +32,8 @@ # include "4ed_debug_mem.h" #endif -#include "4ed_rendering.h" +#include "4ed_render_format.h" +#include "4ed_render_target.h" #include "4ed.h" #include "4ed_buffer_model.h" @@ -43,7 +43,9 @@ #include "4ed_doubly_linked_list.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.cpp" diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 9b4930fc..5998f5be 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -5879,7 +5879,7 @@ draw_file_loaded(System_Functions *system, View *view, Models *models, i32_Rect draw_rectangle_outline(target, char_rect, mark_color); } 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; } diff --git a/4ed_rendering_helper.cpp b/4ed_render_fill.cpp similarity index 59% rename from 4ed_rendering_helper.cpp rename to 4ed_render_fill.cpp index 14ea3b15..5c41dfcc 100644 --- a/4ed_rendering_helper.cpp +++ b/4ed_render_fill.cpp @@ -1,9 +1,9 @@ /* * 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 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 draw_pop_clip(Render_Target *target){ - i32_Rect result = target->pop_clip(target); + i32_Rect result = render_pop_clip(target); return(result); } inline void draw_change_clip(Render_Target *target, i32_Rect clip_box){ - target->pop_clip(target); - target->push_clip(target, clip_box); + render_pop_clip(target); + render_push_clip(target, clip_box); } internal void @@ -50,7 +50,7 @@ draw_rectangle(Render_Target *target, i32_Rect rect, u32 color){ piece.header.type = piece_type_rectangle; piece.rectangle.rect = f32R(rect); piece.rectangle.color = color; - target->push_piece(target, piece); + render_push_piece(target, piece); } internal void @@ -59,24 +59,7 @@ draw_rectangle(Render_Target *target, f32_Rect rect, u32 color){ piece.header.type = piece_type_rectangle; piece.rectangle.rect = rect; piece.rectangle.color = color; - target->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); + render_push_piece(target, piece); } internal void @@ -85,7 +68,7 @@ draw_rectangle_outline(Render_Target *target, f32_Rect rect, u32 color){ piece.header.type = piece_type_outline; piece.rectangle.rect = rect; piece.rectangle.color = color; - target->push_piece(target, piece); + render_push_piece(target, piece); } inline void @@ -107,13 +90,8 @@ draw_margin(Render_Target *target, i32_Rect outer, i32 width, u32 color){ draw_margin(target, outer, inner, color); } -inline internal i32 -font_predict_size(i32 pt_size){ - return pt_size*pt_size*128; -} - 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; piece.header.type = type; 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.font_id = font_id; piece.glyph.codepoint = codepoint; - target->push_piece(target, piece); + render_push_piece(target, piece); } internal void -font_draw_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(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){ + draw_font_glyph(target, font_id, piece_type_glyph, codepoint, x, y, color); } internal f32 @@ -156,7 +134,7 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i if (behavior.do_codepoint_advance){ u32 codepoint = step.value; 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); } @@ -169,7 +147,7 @@ draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_i f32 xx = x; 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]; } } @@ -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); @@ -243,19 +173,6 @@ draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, ch 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 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); diff --git a/4ed_render_format.h b/4ed_render_format.h new file mode 100644 index 00000000..c0016401 --- /dev/null +++ b/4ed_render_format.h @@ -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 + diff --git a/4ed_render_opengl.cpp b/4ed_render_opengl.cpp new file mode 100644 index 00000000..fd04b047 --- /dev/null +++ b/4ed_render_opengl.cpp @@ -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 +#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 + diff --git a/4ed_render_target.cpp b/4ed_render_target.cpp new file mode 100644 index 00000000..a9c98223 --- /dev/null +++ b/4ed_render_target.cpp @@ -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 + diff --git a/4ed_render_target.h b/4ed_render_target.h new file mode 100644 index 00000000..56b800b2 --- /dev/null +++ b/4ed_render_target.h @@ -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 + diff --git a/4ed_rendering.h b/4ed_rendering.h deleted file mode 100644 index 2cd9af0d..00000000 --- a/4ed_rendering.h +++ /dev/null @@ -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 - diff --git a/platform_all/4ed_system_shared.cpp b/platform_all/4ed_system_shared.cpp index d4ae9b89..e778c21b 100644 --- a/platform_all/4ed_system_shared.cpp +++ b/platform_all/4ed_system_shared.cpp @@ -222,598 +222,6 @@ sysshared_to_binary_path(String *out_filename, char *filename){ 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 -#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 // BOTTOM diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 72c1be4c..daaa75d3 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -38,7 +38,8 @@ #include "4ed_system.h" #include "4ed_log.h" -#include "4ed_rendering.h" +#include "4ed_render_format.h" +#include "4ed_render_target.h" #include "4ed.h" #include "4ed_file_track.h" @@ -431,15 +432,14 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ int status; if (pid && waitpid(pid, &status, WNOHANG) > 0){ - close_me = true; - cli->exit = WEXITSTATUS(status); + close_me = true; + close(*(int*)&cli->out_read); + close(*(int*)&cli->out_write); + struct epoll_event 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); @@ -447,6 +447,7 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ #include "4ed_font_data.h" #include "4ed_system_shared.cpp" +#include "4ed_render_opengl.cpp" // // End of system funcs @@ -456,13 +457,6 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ // Renderer // -internal void -LinuxRedrawTarget(){ - launch_rendering(&sysfunc, &target); - //glFlush(); - glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow); -} - internal void LinuxResizeTarget(i32 width, i32 height){ if (width > 0 && height > 0){ @@ -1564,7 +1558,6 @@ main(int argc, char **argv){ // load_app_code(); - link_rendering(); #if defined(FRED_SUPER) load_custom_code(); #else @@ -1840,7 +1833,8 @@ main(int argc, char **argv){ 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){ Cursor c = xcursors[result.mouse_cursor_type]; diff --git a/platform_mac/mac_4ed.cpp b/platform_mac/mac_4ed.cpp index 6986ed9c..eb17ba58 100644 --- a/platform_mac/mac_4ed.cpp +++ b/platform_mac/mac_4ed.cpp @@ -37,7 +37,8 @@ #include "4ed_system.h" #include "4ed_log.h" -#include "4ed_rendering.h" +#include "4ed_render_format.h" +#include "4ed_render_target.h" #include "4ed.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_system_shared.cpp" +#include "4ed_render_opengl.cpp" //////////////////////////////// @@ -539,7 +541,7 @@ osx_step(void){ osx_show_cursor(0, result.mouse_cursor_type); - launch_rendering(&sysfunc, &target); + interpret_render_buffer(&sysfunc, &target); if (result.animating || cli_count > 0){ osx_schedule_step(); @@ -609,7 +611,6 @@ osx_init(){ DBG_POINT(); load_app_code(); - link_rendering(); #if defined(FRED_SUPER) load_custom_code(); #else diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index dba9e70f..cf2a0da0 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -48,7 +48,8 @@ #include "4ed_system.h" #include "4ed_log.h" -#include "4ed_rendering.h" +#include "4ed_render_format.h" +#include "4ed_render_target.h" #include "4ed.h" #include @@ -448,7 +449,7 @@ Sys_CLI_Update_Step_Sig(system_cli_update_step){ internal Sys_CLI_End_Update_Sig(system_cli_end_update){ - b32 close_me = 0; + b32 close_me = false; HANDLE proc = *(HANDLE*)&cli->proc; DWORD result = 0; @@ -460,22 +461,20 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ cli->exit = (i32)result; } - close_me = 1; + close_me = true; CloseHandle(*(HANDLE*)&cli->proc); CloseHandle(*(HANDLE*)&cli->out_read); CloseHandle(*(HANDLE*)&cli->out_write); --win32vars.running_cli; } + return(close_me); } -// -// Linkage to Custom and Application -// - #include "4ed_font_data.h" #include "4ed_system_shared.cpp" +#include "4ed_render_opengl.cpp" // // Helpers @@ -517,13 +516,6 @@ Win32KeycodeInit(){ keycode_lookup_table[VK_F16] = key_f16; } -internal void -Win32RedrawScreen(HDC hdc){ - launch_rendering(&sysfunc, &target); - glFlush(); - SwapBuffers(hdc); -} - internal void Win32Resize(i32 width, i32 height){ if (width > 0 && height > 0){ @@ -932,7 +924,8 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ win32vars.got_useful_event = true; PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); - Win32RedrawScreen(hdc); + // NOTE(allen): Do nothing? + AllowLocal(hdc); EndPaint(hwnd, &ps); }break; @@ -948,11 +941,6 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ win32vars.got_useful_event = true; }break; - case WM_CANCELMODE: - { - result = DefWindowProc(hwnd, uMsg, wParam, lParam); - }break; - default: { result = DefWindowProc(hwnd, uMsg, wParam, lParam); @@ -1006,7 +994,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS // load_app_code(); - link_rendering(); #if defined(FRED_SUPER) load_custom_code(); #else @@ -1396,7 +1383,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS win32vars.lctrl_lalt_is_altgr = result.lctrl_lalt_is_altgr; HDC hdc = GetDC(win32vars.window_handle); - Win32RedrawScreen(hdc); + interpret_render_buffer(&sysfunc, &target); + SwapBuffers(hdc); ReleaseDC(win32vars.window_handle, hdc); win32vars.first = 0; diff --git a/string/internal_4coder_string.cpp b/string/internal_4coder_string.cpp index 3669cd14..db3bf825 100644 --- a/string/internal_4coder_string.cpp +++ b/string/internal_4coder_string.cpp @@ -1283,7 +1283,12 @@ replace_range_str(String *str, i32_4tech first, i32_4tech one_past_last, String CPP_NAME(replace_str) 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; for (;;){ i = find_substr_s(*str, i, replace); @@ -1297,21 +1302,36 @@ replace_str_ss(String *str, String replace, String with){ CPP_NAME(replace_str) 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); replace_str_ss(str, replace, w); } CPP_NAME(replace_str) 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); replace_str_ss(str, r, with); } CPP_NAME(replace_str) 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 w = make_string_slowly(with); replace_str_ss(str, r, w);