// Returns the index for a free list with a block to fit the size request static int get_free_list_index(size_t size){ REQUIRES(0 < size && size <= 0x3FFFFFFF); int index = 0; size = nearest_power_2(size); // calculate log base 2 while (size >>= 1) index++; //lowest index is for size 2^5 index -= 5; ENSURES(0 <= index && index < NUM_FREE_LISTS); return index; }
texture *font_impl::get_glyph(const wchar_t ch) const { shared_pointer<texture> tex = glyph_textures[ch]; if (!tex.ptr()) { int minx, maxx, miny, maxy, advance; if (TTF_GlyphMetrics(static_cast<TTF_Font *>(ttf_font_ptr), ch, &minx, &maxx, &miny, &maxy, &advance) == -1) throw runtime_exception(L"Error getting glyph metrics: %hs", TTF_GetError()); SDL_Color c; c.r = static_cast<Uint8>(fg[color::COMPONENT_RED] * 255.0f); c.g = static_cast<Uint8>(fg[color::COMPONENT_GREEN] * 255.0f); c.b = static_cast<Uint8>(fg[color::COMPONENT_BLUE] * 255.0f); SDL_Surface *surf1 = TTF_RenderGlyph_Blended(static_cast<TTF_Font *>(ttf_font_ptr), ch, c); SDL_Surface *surf2 = SDL_CreateRGBSurface(SDL_SWSURFACE, nearest_power_2(minx + surf1->w), texture_height, 32, surf1->format->Rmask, surf1->format->Gmask, surf1->format->Bmask, surf1->format->Amask); if (!surf2) throw runtime_exception(L"Unable to create SDL surface: %hs", SDL_GetError()); SDL_Rect dest; dest.x = minx > 0 ? minx : 0; dest.y = (surf2->h - font_height) + (font_ascent - maxy); dest.w = surf1->w; dest.h = surf1->h; clear_pixel_alpha(surf2); src_alpha_blit(surf1, surf2, dest.x, dest.y); string glyph_id = string::format(L"%ls %d: %lc", face.w_string(), size, ch); tex = new texture(FONT_TEXTURE_CATEGORY, surf2, texture::TEXTURE_ENV_REPLACE | texture::TEXTURE_WRAP_CLAMP | texture::TEXTURE_FILTER_LINEAR, texture::TEXTURE_COLORMAP, glyph_id.w_string()); glyph_textures[ch] = tex; glyph_pct_x[ch] = static_cast<float>(advance) / static_cast<float>(surf2->w); glyph_pct_y[ch] = static_cast<float>(font_height) / static_cast<float>(surf2->h); glyph_widths[ch] = static_cast<float>(advance); SDL_FreeSurface(surf2); SDL_FreeSurface(surf1); } return tex.ptr(); } // font_impl::get_glyph()
font_impl::font_impl(const string & face, int size, const color & fg) : face(face), size(size), ttf_font_ptr(0), fg(fg) { gsgl::log(string::format(L"font_impl: creating %ls %d (%f, %f, %f)", face.w_string(), size, fg[color::COMPONENT_RED], fg[color::COMPONENT_GREEN], fg[color::COMPONENT_BLUE])); if (FONT_DIR.is_empty()) get_font_dir(); // common font names string fname = FONT_DIR; #ifdef WIN32 if (face == L"Mono") { fname += L"cour.ttf"; } else if (face == L"Sans") { fname += L"arial.ttf"; } else { throw runtime_exception(L"Unable to determine font file name for '%ls'", face.w_string()); } #else #error Font name lookup unimplemented! #endif // ttf_font_ptr = TTF_OpenFont(fname.c_string(), size); if (!ttf_font_ptr) throw runtime_exception(L"Unable to load font '%ls': %hs", face.w_string(), TTF_GetError()); // font_height = TTF_FontHeight(static_cast<TTF_Font *>(ttf_font_ptr)); font_ascent = TTF_FontAscent(static_cast<TTF_Font *>(ttf_font_ptr)); texture_height = nearest_power_2(font_height); } // font_impl::font_impl()