// ---------------------------------------------------------------------------- size_t vertex_buffer_insert( vertex_buffer_t * self, size_t index, void * vertices, size_t vcount, GLuint * indices, size_t icount ) { assert( self ); assert( vertices ); assert( indices ); self->state = FROZEN; // Push back vertices size_t vstart = vector_size( self->vertices ); vertex_buffer_push_back_vertices( self, vertices, vcount ); // Push back indices size_t istart = vector_size( self->indices ); vertex_buffer_push_back_indices( self, indices, icount ); // Update indices within the vertex buffer size_t i; for( i=0; i<icount; ++i ) { *(GLuint *)(vector_get( self->indices, istart+i )) += vstart; } // Insert item ivec4 item = {{ vstart, vcount, istart, icount }}; vector_insert( self->items, index, &item ); self->state = DIRTY; return index; }
// -------------------------------------------------------------- add_glyph --- void add_glyph( const texture_glyph_t * glyph, vertex_buffer_t * buffer, const markup_t * markup, vec2 *pen, float kerning ) { if( p_kerning ) { pen->x += kerning; } else { } float r = markup->foreground_color.r; float g = markup->foreground_color.g; float b = markup->foreground_color.b; float a = markup->foreground_color.a; float x0 = ( pen->x + glyph->offset_x ); float y0 = (int)( pen->y + glyph->offset_y ); float x1 = ( x0 + glyph->width * p_width ); float y1 = (int)( y0 - glyph->height ); float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3}; float dx = tan(p_faux_italic/180.0 * M_PI) * (glyph->height); vertex_t vertices[] = { { (int)(x0+dx),y0,0, s0,t0, r,g,b,a, x0+dx-((int)(x0+dx)) }, { (int)(x0 ),y1,0, s0,t1, r,g,b,a, x0-((int)x0) }, { (int)(x1 ),y1,0, s1,t1, r,g,b,a, x1-((int)x1) }, { (int)(x1+dx),y0,0, s1,t0, r,g,b,a, x1+dx-((int)(x1+dx)) } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); pen->x += glyph->advance_x * (1.0 + p_interval); pen->y += glyph->advance_y; }
// --------------------------------------------------------------- add_text --- void add_text( vertex_buffer_t * buffer, texture_font_t * font, wchar_t * text, vec4 * color, vec2 * pen ) { size_t i; float r = color->red, g = color->green, b = color->blue, a = color->alpha; for( i=0; i<wcslen(text); ++i ) { texture_glyph_t *glyph = texture_font_get_glyph( font, text[i] ); if( glyph != NULL ) { int kerning = 0; if( i > 0) { kerning = texture_glyph_get_kerning( glyph, text[i-1] ); } pen->x += kerning; float x0 = ( pen->x + glyph->offset_x ); float y0 = (int)( pen->y + glyph->offset_y ); float x1 = ( x0 + glyph->width ); float y1 = (int)( y0 - glyph->height ); float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3}; vertex_t vertices[] = { { (int)x0,y0,0, s0,t0, r,g,b,a, x0-((int)x0) }, { (int)x0,y1,0, s0,t1, r,g,b,a, x0-((int)x0) }, { (int)x1,y1,0, s1,t1, r,g,b,a, x1-((int)x1) }, { (int)x1,y0,0, s1,t0, r,g,b,a, x1-((int)x1) } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); pen->x += glyph->advance_x; pen->y += glyph->advance_y; } } }
// ---------------------------------------------------------------------------- size_t vertex_buffer_insert( vertex_buffer_t * self, const size_t index, const void * vertices, const size_t vcount, const GLuint * indices, const size_t icount ) { size_t vstart, istart, i; ivec4 item; assert( self ); assert( vertices ); assert( indices ); self->state = FROZEN; // Push back vertices vstart = vector_size( self->vertices ); vertex_buffer_push_back_vertices( self, vertices, vcount ); // Push back indices istart = vector_size( self->indices ); vertex_buffer_push_back_indices( self, indices, icount ); // Update indices within the vertex buffer for( i=0; i<icount; ++i ) { *(GLuint *)(vector_get( self->indices, istart+i )) += vstart; } // Insert item item.x = vstart; item.y = vcount; item.z = istart; item.w = icount; vector_insert( self->items, index, &item ); self->state = DIRTY; return index; }
// --------------------------------------------------------------- add_text --- void add_text( vertex_buffer_t * buffer, texture_font_t * font, char *text, vec2 pen, vec4 fg_color_1, vec4 fg_color_2 ) { size_t i; for( i = 0; i < strlen(text); ++i ) { texture_glyph_t *glyph = texture_font_get_glyph( font, text + i ); float kerning = 0.0f; if( i > 0) { kerning = texture_glyph_get_kerning( glyph, text + i - 1 ); } pen.x += kerning; /* Actual glyph */ float x0 = ( pen.x + glyph->offset_x ); float y0 = (int)( pen.y + glyph->offset_y ); float x1 = ( x0 + glyph->width ); float y1 = (int)( y0 - glyph->height ); float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3}; vertex_t vertices[] = { { (int)x0,y0,0, s0,t0, fg_color_1 }, { (int)x0,y1,0, s0,t1, fg_color_2 }, { (int)x1,y1,0, s1,t1, fg_color_2 }, { (int)x1,y0,0, s1,t0, fg_color_1 } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); pen.x += glyph->advance_x; } }
// --------------------------------------------------------------- add_text --- void add_text( vertex_buffer_t * buffer, vec2 * pen, ... ) { markup_t *markup; char *text; va_list args; va_start ( args, pen ); do { markup = va_arg( args, markup_t * ); if( markup == NULL ) { break; } text = va_arg( args, char * ); size_t i; texture_font_t * font = markup->font; float r = markup->foreground_color.red; float g = markup->foreground_color.green; float b = markup->foreground_color.blue; float a = markup->foreground_color.alpha; for( i = 0; i < strlen(text); ++i ) { texture_glyph_t *glyph = texture_font_get_glyph( font, text + i ); if( glyph != NULL ) { float kerning = 0.0f; if( i > 0) { kerning = texture_glyph_get_kerning( glyph, text + i - 1 ); } pen->x += kerning; /* Actual glyph */ float x0 = ( pen->x + glyph->offset_x ); float y0 = (int)( pen->y + glyph->offset_y ); float x1 = ( x0 + glyph->width ); float y1 = (int)( y0 - glyph->height ); float s0 = glyph->s0; float t0 = glyph->t0; float s1 = glyph->s1; float t1 = glyph->t1; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3 }; vertex_t vertices[] = { { (int)x0,y0,0, s0,t0, r,g,b,a }, { (int)x0,y1,0, s0,t1, r,g,b,a }, { (int)x1,y1,0, s1,t1, r,g,b,a }, { (int)x1,y0,0, s1,t0, r,g,b,a } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); pen->x += glyph->advance_x; } } } while( markup != 0 ); va_end ( args ); }
/* ------------------------------------------------------------------------- */ void texture_glyph_add_to_vertex_buffer( const TextureGlyph *self, VertexBuffer *buffer, const Markup *markup, Pen *pen, int kerning ) { TextureFont *font = self->font; float r = 1; float g = 1; float b = 1; float a = 1; int rise = 0; int spacing = 0; if( markup ) { rise = markup->rise; spacing = markup->spacing; } pen->x += kerning; // Background if( markup && markup->background_color.a > 0 ) { float u0 = font->atlas->black.x / (float) font->atlas->width; float v0 = font->atlas->black.y / (float) font->atlas->height; float u1 = u0 + font->atlas->black.width / (float) font->atlas->width; float v1 = v0 + font->atlas->black.height / (float) font->atlas->height; int x0 = pen->x - kerning; int y0 = pen->y + font->descender; int x1 = x0 + self->advance_x + markup->spacing + kerning; int y1 = y0 + font->height - font->linegap; r = markup->background_color.r; g = markup->background_color.g; b = markup->background_color.b; a = markup->background_color.a; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3}; TextureGlyphVertex vertices[] = { { x0,y0,0, u0,v0, r,g,b,a }, { x0,y1,0, u0,v1, r,g,b,a }, { x1,y1,0, u1,v1, r,g,b,a }, { x1,y0,0, u1,v0, r,g,b,a } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); } // Underline // Overline // Outline // Strikethrough // Actual glyph if( markup ) { r = markup->foreground_color.r; g = markup->foreground_color.g; b = markup->foreground_color.b; a = markup->foreground_color.a; } int x0_ = (int)( pen->x + self->offset_x ); int y0_ = (int)( pen->y + self->offset_y + rise ); int x1_ = (int)( x0_ + self->width ); int y1_ = (int)( y0_ - self->height ); float x0 = x0_; float y0 = y0_; float x1 = x1_; float y1 = y1_; float u0 = self->u0; float v0 = self->v0; float u1 = self->u1; float v1 = self->v1; GLuint index = buffer->vertices->size; GLuint indices[] = {index, index+1, index+2, index, index+2, index+3}; TextureGlyphVertex vertices[] = { { x0,y0,0, u0,v0, r,g,b,a }, { x0,y1,0, u0,v1, r,g,b,a }, { x1,y1,0, u1,v1, r,g,b,a }, { x1,y0,0, u1,v0, r,g,b,a } }; vertex_buffer_push_back_indices( buffer, indices, 6 ); vertex_buffer_push_back_vertices( buffer, vertices, 4 ); pen->x += self->advance_x + spacing; pen->y += self->advance_y; }
// ----------------------------------------------------------- make_segment --- void make_segment( vertex_buffer_t * buffer, float x0, float y0, float x1, float y1, float thickness, float r, float g, float b, float a ) { assert( (x1 != x0) || (y1 != y0) ); assert( thickness != 0 ); float d = sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ); float dx, dy, t; if (thickness < 2.0) { dx = (x1-x0)/d*0.5*2; dy = (y1-y0)/d*0.5*2; d = 2.0 - thickness/2.0; t = thickness/2.0; } else if (thickness < 3.0) { dx = (x1-x0)/d*0.5*3; dy = (y1-y0)/d*0.5*3; d = 2.5 - thickness/2.0; t = 1.0; } else { dx = (x1-x0)/d*0.5*thickness; dy = (y1-y0)/d*0.5*thickness; d = 1.0; t = 1.0; } vertex_t body[6] = { {x0+dy,y0-dx, 0,-d, r,g,b,a, t}, {x0-dy,y0+dx, 0,+d, r,g,b,a, t}, {x1-dy,y1+dx, 0,+d, r,g,b,a, t}, {x0+dy,y0-dx, 0,-d, r,g,b,a, t}, {x1-dy,y1+dx, 0,+d, r,g,b,a, t}, {x1+dy,y1-dx, 0,-d, r,g,b,a, t} }; vertex_buffer_push_back_vertices ( buffer, body, 6); // If line is too thin, no caps if( thickness < 1.0 ) { return; } // Line Cap 0 vertex_t cap0[6] = { {x0+dy, y0-dx, 0,-1, r,g,b,a, t}, {x0-dy, y0+dx, 0,+1, r,g,b,a, t}, {x0-dy-dx,y0+dx-dy, +1,+1, r,g,b,a, t}, {x0+dy, y0-dx, 0,-1, r,g,b,a, t}, {x0-dy-dx,y0+dx-dy, +1,+1, r,g,b,a, t}, {x0+dy-dx,y0-dx-dy, +1,-1, r,g,b,a, t} }; vertex_buffer_push_back_vertices ( buffer, cap0, 6); // Line Cap 1 vertex_t cap1[6] = { {x1-dy, y1+dx, 0,-1, r,g,b,a, t}, {x1+dy, y1-dx, 0,+1, r,g,b,a, t}, {x1+dy+dx, y1-dx+dy, +1,+1, r,g,b,a, t}, {x1-dy, y1+dx, 0,-1, r,g,b,a, t}, {x1+dy+dx, y1-dx+dy, +1,+1, r,g,b,a, t}, {x1-dy+dx, y1+dx+dy, +1,-1, r,g,b,a, t} }; vertex_buffer_push_back_vertices ( buffer, cap1, 6); }