diff options
-rw-r--r-- | buffer.c | 19 | ||||
-rw-r--r-- | main.c | 16 | ||||
-rw-r--r-- | text.c | 40 |
3 files changed, 56 insertions, 19 deletions
@@ -118,15 +118,22 @@ void text_buffer_free(TextBuffer *buffer) { } // Render the text buffer in the given rectangle -void text_buffer_render(TextBuffer *buffer, Font *font, float box_x, float box_y, float box_w, float box_h) { +void text_buffer_render(TextBuffer *buffer, Font *font, float x1, float y1, float x2, float y2) { mbstate_t mbstate = {0}; uint nblocks = buffer->nblocks; TextBlock *blocks = buffer->blocks; + glBegin(GL_LINE_LOOP); + glVertex2f(x1,y1); + glVertex2f(x1,y2); + glVertex2f(x2,y2); + glVertex2f(x2,y1); + glEnd(); + text_chars_begin(font); TextRenderState text_state = { - .x = box_x, .y = box_y, - .min_x = box_x, .min_y = box_y, - .max_x = box_x+box_w, .max_y = box_y+box_h + .x = x1, .y = y1 + text_font_char_height(font), + .min_x = x1, .min_y = y1, + .max_x = x2, .max_y = y2 }; for (uint block_idx = 0; block_idx < nblocks; ++block_idx) { @@ -154,8 +161,8 @@ void text_buffer_render(TextBuffer *buffer, Font *font, float box_x, float box_y } switch (c) { case L'\n': - text_state.x = box_x; - text_state.y -= text_font_char_height(font); + text_state.x = x1; + text_state.y += text_font_char_height(font); break; case L'\r': break; // for CRLF line endings case L'\t': @@ -1,3 +1,4 @@ + #include "base.h" no_warn_start #if _WIN32 @@ -96,15 +97,20 @@ int main(void) { glViewport(0, 0, window_width, window_height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - glOrtho(0, window_width, 0, window_height, -1, +1); + // pixel coordinates; down is positive y + glOrtho(0, window_width, window_height, 0, -1, +1); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1,1,1); - text_buffer_render(&text_buffer, font, 50, window_heightf-50, window_widthf-100, window_heightf-100); - if (text_has_err()) { - printf("Text error: %s\n", text_get_err()); - break; + + { + float x1 = 50, y1 = 50, x2 = window_widthf-50, y2 = window_heightf-50; + text_buffer_render(&text_buffer, font, x1, y1, x2, y2); + if (text_has_err()) { + printf("Text error: %s\n", text_get_err()); + break; + } } //text_buffer_print_debug(&text_buffer); @@ -178,16 +178,40 @@ void text_render_char(Font *font, char32_t c, TextRenderState *state) { stbtt_bakedchar *char_data = font->char_pages[page]; if (char_data) { // if page was successfully loaded stbtt_aligned_quad q = {0}; - // because stb_truetype uses down is positive, we need to negate the y - // coordinate, pass it into the function, then negate it back. - state->y = -state->y; stbtt_GetBakedQuad(char_data, font->tex_widths[page], font->tex_heights[page], (int)index, &state->x, &state->y, &q, 1); - state->y = -state->y; - 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); + float s0 = q.s0, t0 = q.t0; + float s1 = q.s1, t1 = q.t1; + float x0 = q.x0, y0 = q.y0; + float x1 = q.x1, y1 = q.y1; + float const min_x = state->min_x, max_x = state->max_x; + float const min_y = state->min_y, max_y = state->max_y; + if (x0 > max_x || y0 > max_y || x1 < min_x || y1 < min_y) + return; + if (x0 < min_x) { + // left side of character is clipped + s0 = (min_x-x0) / (x1-x0) * (s1-s0) + s0; + x0 = min_x; + } + if (x1 >= max_x) { + // right side of character is clipped + s1 = (max_x-x0) / (x1-x0) * (s1-s0) + s0; + x1 = max_x; + } + if (y0 < min_y) { + // top side of character is clipped + t0 = (min_y-y0) / (y1-y0) * (t1-t0) + t0; + y0 = min_y; + } + if (y1 >= max_y) { + // bottom side of character is clipped + t1 = (max_y-y0) / (y1-y0) * (t1-t0) + t0; + y1 = max_y; + } + glTexCoord2f(s0,t0); glVertex2f(x0,y0); + glTexCoord2f(s0,t1); glVertex2f(x0,y1); + glTexCoord2f(s1,t1); glVertex2f(x1,y1); + glTexCoord2f(s1,t0); glVertex2f(x1,y0); } } |