void font_set_glyph_to_image(struct vg_font *font, VGuint glyphIndex, struct vg_image *image, const VGfloat glyphOrigin[2], const VGfloat escapement[2]) { add_glyph(font, glyphIndex, (struct vg_object *) image, VG_TRUE, glyphOrigin, escapement); }
void font_set_glyph_to_path(struct vg_font *font, VGuint glyphIndex, struct path *path, VGboolean isHinted, const VGfloat glyphOrigin[2], const VGfloat escapement[2]) { add_glyph(font, glyphIndex, (struct vg_object *) path, isHinted, glyphOrigin, escapement); }
const TileSet::TileLocation& TextTileSet::get_tile_location(unsigned int id) { const auto* cell = m_tiles.get_item(id); if(cell != nullptr) { return *cell; } else { auto& new_cell = m_free_slots.back(); m_free_slots.pop_back(); const auto& new_cell_ret = m_tiles.add_item(id, new_cell); add_glyph(new_cell, id); return new_cell_ret; } }
float text_show(float x, float y, char *str) { int ucs, gid; int kern; int left = 0; while (*str) { str += chartorune(&ucs, str); gid = stbtt_FindGlyphIndex(&text_font->info, ucs); kern = stbtt_GetGlyphKernAdvance(&text_font->info, left, gid); x += add_glyph(gid, x, y); x += kern * text_scale; left = gid; } return x; }
const text_extents & font::get_glyph( char32_t char_code ) { auto i = _glyph_cache.find( char_code ); if ( i == _glyph_cache.end() ) { // We are only loading a grayscale bitmap for now. Could // set the LCD filtering and load a color bitmap // also, we could switch to the signed distance field stuff // fairly easily if we added the computation here and used // the appropriate shader... FT_Int32 flags = FT_LOAD_TARGET_NORMAL | FT_LOAD_RENDER;// | FT_LOAD_FORCE_AUTOHINT; FT_UInt index = FT_Get_Char_Index( _face, char_code ); auto err = FT_Load_Glyph( _face, index, flags ); if ( err ) throw std::runtime_error( "Unable to load glyph" ); FT_GlyphSlot slot = _face->glyph; int w = static_cast<int>( slot->bitmap.width ); int h = static_cast<int>( slot->bitmap.rows ); if ( w > 0 && h > 0 ) { const uint8_t *glData = slot->bitmap.buffer; add_glyph( char_code, glData, slot->bitmap.pitch, w, h ); } text_extents &gle = _glyph_cache[char_code]; // err = FT_Load_Glyph( _face, nglyph->index(), FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING ); gle.x_bearing = static_cast<double>( slot->metrics.horiBearingX ) / 64.0; gle.y_bearing = static_cast<double>( slot->metrics.horiBearingY ) / 64.0; gle.width = static_cast<double>( slot->metrics.width ) / 64.0; gle.height = static_cast<double>( slot->metrics.height ) / 64.0; gle.x_advance = static_cast<double>( slot->metrics.horiAdvance ) / 64.0; gle.y_advance = static_cast<double>( slot->metrics.vertAdvance ) / 64.0; return gle; } return i->second; }
// ----------------------------------------------------------- build_buffer --- void build_buffer( void ) { vec2 pen; size_t i; texture_font_t *font; texture_glyph_t *glyph; vec4 white = {{1.0, 1.0, 1.0, 1.0}}; vec4 none = {{1.0, 1.0, 1.0, 0.0}}; markup_t markup = { .family = "Arial", .size = 10.0, .bold = 0, .italic = 0, .rise = 0.0, .spacing = 0.0, .gamma = 2.2, .foreground_color = white, .background_color = none, .underline = 0, .underline_color = white, .overline = 0, .overline_color = white, .strikethrough = 0, .strikethrough_color = white, .font = 0, }; vertex_buffer_clear( buffer ); texture_atlas_clear( atlas ); if( p_family == VERA) { font = texture_font_new( atlas, "fonts/Vera.ttf", p_size ); } else if( p_family == VERA_MONO) { font = texture_font_new( atlas, "fonts/VeraMono.ttf", p_size ); } else if( p_family == GEORGIA) { font = texture_font_new( atlas, "fonts/Georgia.ttf", p_size ); } else if( p_family == TIMES ) { font = texture_font_new( atlas, "fonts/Times.ttf", p_size ); } else if( p_family == TAHOMA ) { font = texture_font_new( atlas, "fonts/Tahoma.ttf", p_size ); } else if( p_family == ARIAL ) { font = texture_font_new( atlas, "fonts/Arial.ttf", p_size ); } else if( p_family == VERDANA ) { font = texture_font_new( atlas, "fonts/Verdana.ttf", p_size ); } else { fprintf( stderr, "Error : Unknown family type\n" ); return; } font->hinting = p_hinting; font->filtering = 1; float norm = 1.0/(p_primary + 2*p_secondary + 2*p_tertiary); font->lcd_weights[0] = (unsigned char)(p_tertiary*norm*256); font->lcd_weights[1] = (unsigned char)(p_secondary*norm*256); font->lcd_weights[2] = (unsigned char)(p_primary*norm*256); font->lcd_weights[3] = (unsigned char)(p_secondary*norm*256); font->lcd_weights[4] = (unsigned char)(p_tertiary*norm*256); texture_font_load_glyphs( font, L" !\"#$%&'()*+,-./0123456789:;<=>?" L"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" L"`abcdefghijklmnopqrstuvwxyz{|}~" ); pen.x = 10; pen.y = 600 - font->height - 10; glyph = texture_font_get_glyph( font, text[0] ); add_glyph( glyph, buffer, &markup, &pen, 0 ); for( i=1; i<wcslen(text); ++i ) { if( text[i] == '\n' ) { pen.x = 10; pen.y -= font->height; // + 0.01*(size - (int)size)*font->height; } else { glyph = texture_font_get_glyph( font, text[i] ); float kerning = 0.0; if( p_kerning ) { kerning = texture_glyph_get_kerning( glyph, text[i-1] ); } add_glyph( glyph, buffer, &markup, &pen, kerning ); } } texture_font_delete (font ); } // ---------------------------------------------------------------- display --- void display(void) { if( p_invert ) { glClearColor( 0, 0, 0, 1 ); } else { glClearColor( 1, 1, 1, 1 ); } glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glEnable( GL_TEXTURE_2D ); glBindTexture( GL_TEXTURE_2D, atlas->id ); if( !p_lcd_filtering ) { glEnable( GL_COLOR_MATERIAL ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( p_invert ) { glColor4f(1,1,1,1); } else { glColor4f(0,0,0,1); } } else { glEnable( GL_COLOR_MATERIAL ); glBlendFunc( GL_CONSTANT_COLOR_EXT, GL_ONE_MINUS_SRC_COLOR ); glEnable( GL_BLEND ); glColor3f( 1,1,1 ); if( p_invert ) { glBlendColor( 1, 1, 1, 1 ); } else { glBlendColor( 0, 0, 0, 1 ); } } if( !p_lcd_filtering ) { vertex_buffer_render( buffer, GL_TRIANGLES, "vt" ); } else { glUseProgram( program ); glUniform1i( texture_location, 0 ); glUniform1f( gamma_location, p_gamma ); float norm = 1.0/(p_primary+2*p_secondary+2*p_tertiary); glUniform1f( primary_location, p_primary*norm ); glUniform1f( secondary_location, p_secondary*norm ); glUniform1f( tertiary_location, p_tertiary*norm ); glUniform2f( pixel_location, 1.0/atlas->width, 1.0/atlas->height ); vertex_buffer_render( buffer, GL_TRIANGLES, "vtc" ); glUseProgram( 0 ); } TwDraw( ); glutSwapBuffers( ); } // ---------------------------------------------------------------- reshape --- void reshape( int width, int height ) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1, 1); glMatrixMode(GL_MODELVIEW); TwWindowSize( width, height ); }
static int text_buffer_add_wchar( text_buffer_t * self, vec2 * pen, markup_t * markup, texture_font_t * font, wchar_t current, wchar_t previous ) { float gamma = markup->gamma; // Maximum number of vertices is 20 (= 5x2 triangles) per glyph: // - 2 triangles for background // - 2 triangles for overline // - 2 triangles for underline // - 2 triangles for strikethrough // - 2 triangles for glyph glyph_vertex_t vertices[4*5]; GLuint indices[6*5]; struct coordinates coors = { vertices, vertices, vertices + sizeof vertices / sizeof *vertices, indices, indices, indices + sizeof indices / sizeof *indices }; if( current == L'\n' ) { pen->x = self->origin.x; pen->y += (int)(self->line_descender); self->line_descender = 0; self->line_ascender = 0; self->line_start = vector_size( self->buffer->items ); return 0; } texture_glyph_t *glyph = glyph_cache_get_glyph( &self->cache, font, current ); if(glyph == NULL) return -1; texture_glyph_t *black = glyph_cache_get_glyph( &self->cache, NULL, -1 ); float kerning = previous ? glyph_cache_get_kerning( &self->cache, glyph, previous ) : 0; pen->x += kerning; // Background if( markup->background_color.alpha > 0 ) { add_glyph(&coors, pen, &markup->background_color, -kerning, font->descender, glyph->advance.x, font->height + font->linegap, gamma, black); } // Underline if( markup->underline ) { add_glyph(&coors, pen, &markup->underline_color, -kerning, font->underline_position, glyph->advance.x, font->underline_thickness, gamma, black); } // Overline if( markup->overline ) { add_glyph(&coors, pen, &markup->overline_color, -kerning, (int)font->ascender, glyph->advance.x, (int)font->underline_thickness, gamma, black); } // Actual glyph add_glyph(&coors, pen, &markup->foreground_color, glyph->bearing.x, glyph->bearing.y, glyph->size.x, -(float)glyph->size.y, gamma, glyph); /* Strikethrough */ if( markup->strikethrough ) { add_glyph(&coors, pen, &markup->strikethrough_color, -kerning, (int)font->ascender*.33, glyph->advance.x, font->underline_thickness, gamma, black); } coors_push_to_vector( &coors, self->buffer ); pen->x += glyph->advance.x; return 0; }