cleaning up opengl code
							parent
							
								
									d04dd8879b
								
							
						
					
					
						commit
						c0bf8966eb
					
				
							
								
								
									
										7
									
								
								4ed.cpp
								
								
								
								
							
							
						
						
									
										7
									
								
								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); | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
|  |  | |||
|  | @ -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); | ||||
|  | @ -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
 | ||||
| 
 | ||||
|  | @ -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
 | ||||
| 
 | ||||
|  | @ -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
 | ||||
| 
 | ||||
|  | @ -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
 | ||||
| 
 | ||||
							
								
								
									
										122
									
								
								4ed_rendering.h
								
								
								
								
							
							
						
						
									
										122
									
								
								4ed_rendering.h
								
								
								
								
							|  | @ -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
 | ||||
| 
 | ||||
|  | @ -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 <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 | ||||
| 
 | ||||
| // BOTTOM
 | ||||
|  |  | |||
|  | @ -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]; | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 <Windows.h> | ||||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Allen Webster
						Allen Webster