/* load a font from a ttf file with the given fontindex and pointsize as font font_id */ int vultures_load_font (int font_id, const char * ttf_filename, int fontindex, int pointsize) { TTF_Font * newfont; if(!TTF_WasInit()) { if(TTF_Init()==-1) return FALSE; if (!vultures_fonts) vultures_fonts = (struct vultures_font *)calloc(VULTURES_MAX_FONTS, sizeof(struct vultures_font)); } /* font_id should always be passed as a #define, which is always < VULTURES_MAX_FONTS */ if (font_id >= VULTURES_MAX_FONTS) return FALSE; newfont = TTF_OpenFontIndex(ttf_filename, pointsize, fontindex); if (!newfont) return FALSE; if (vultures_fonts[font_id].fontptr) TTF_CloseFont(vultures_fonts[font_id].fontptr); vultures_fonts[font_id].fontptr = newfont; vultures_fonts[font_id].lineheight = TTF_FontAscent(newfont) + 2; return TRUE; }
bool TextSupervisor::LoadFont(const std::string &filename, const std::string &font_name, uint32 size) { // Make sure that the font name is not already taken if(IsFontValid(font_name) == true) { IF_PRINT_WARNING(VIDEO_DEBUG) << "a font with the desired reference name already existed: " << font_name << std::endl; return false; } if(size == 0) { IF_PRINT_WARNING(VIDEO_DEBUG) << "attempted to load a font of point size zero" << font_name << std::endl; return false; } // Attempt to load the font TTF_Font *font = TTF_OpenFont(filename.c_str(), size); if(font == NULL) { IF_PRINT_WARNING(VIDEO_DEBUG) << "call to TTF_OpenFont() failed to load the font file: " << filename << std::endl; return false; } // Create a new FontProperties object for this font and set all of the properties according to SDL_ttf FontProperties *fp = new FontProperties; fp->ttf_font = font; fp->height = TTF_FontHeight(font); fp->line_skip = TTF_FontLineSkip(font); fp->ascent = TTF_FontAscent(font); fp->descent = TTF_FontDescent(font); // Create the glyph cache for the font and add it to the font map fp->glyph_cache = new std::vector<FontGlyph *>; _font_map[font_name] = fp; return true; } // bool TextSupervisor::LoadFont(...)
Font::Font(const char *aaddress, int alength, int apointSize, int astyle, float afgRed, float afgGreen, float afgBlue, float abgRed, float abgGreen, float abgBlue) : height(), ascent(), descent(), lineSkip(), address( aaddress), length(alength), pointSize(apointSize), style(astyle), fgRed( afgRed), fgGreen(afgGreen), fgBlue(afgBlue), bgRed(abgRed), bgGreen( abgGreen), bgBlue(abgBlue), ttfFont(), foreground(), background() { int i; ttfFont = open_font(address, pointSize); TTF_SetFontStyle(ttfFont, style); foreground.r = (Uint8) (255 * fgRed); foreground.g = (Uint8) (255 * fgGreen); foreground.b = (Uint8) (255 * fgBlue); background.r = (Uint8) (255 * bgRed); background.g = (Uint8) (255 * bgGreen); background.b = (Uint8) (255 * bgBlue); height = TTF_FontHeight(ttfFont); ascent = TTF_FontAscent(ttfFont); descent = TTF_FontDescent(ttfFont); lineSkip = TTF_FontLineSkip(ttfFont); for (i = minGlyph; i <= maxGlyph; i++) { glyphs[i].pic = NULL; glyphs[i].tex = 0; } }
Font_FT::Glyph::Glyph(TTF_Font *font_, const unsigned char &c, SDL_Surface *source, SDL_Surface *render_target, const SDL_Rect &dstrect, const int &total_width, const int &total_height, const float &vratio) : m_glyph_width(0) { int minx, maxy, glyph_width; TTF_GlyphMetrics(font_, c, &minx, 0, 0, &maxy, &glyph_width); m_glyph_width = glyph_width / vratio; m_upper_left_point.x = float(minx) / vratio; m_upper_left_point.y = float(TTF_FontAscent(font_) - maxy) / vratio; m_lower_right_point.x = m_upper_left_point.x + source->w / vratio; m_lower_right_point.y = m_upper_left_point.y + source->h / vratio; SDL_Rect dstrect2 = {dstrect.x, dstrect.y, Uint16(source->w), Uint16(source->h)}; m_upper_left_texel.x = float(dstrect2.x) / float(total_width); m_upper_left_texel.y = float(dstrect2.y) / float(total_height); m_lower_right_texel.x = float(dstrect2.x + source->w) / float(total_width); m_lower_right_texel.y = float(dstrect2.y + source->h) / float(total_height); SDL_BlitSurface(source, 0, render_target, &dstrect2); SDL_FreeSurface(source); }
static void cache_glyphs() { int top=999, bottom=-999; start_color(); for(int ch=0; ch<128; ch++) { for(int color=0; color<16; color++) { SDL_Surface * glyph = glyph_cache[ch][color] = (fontblending?TTF_RenderGlyph_Blended:TTF_RenderGlyph_Solid)(font, ch, windowsPalette[color]); int minx, maxx, miny, maxy, advance; if(glyph!=NULL && color==0 && 0==TTF_GlyphMetrics(font, ch, &minx, &maxx, &miny, &maxy, &advance) ) { int t = TTF_FontAscent(font)-maxy; int b = t + glyph->h; if(t<top) top = t; if(b>bottom) bottom = b; } } } int height = bottom - top; int delta = (fontheight-height)/2; ttf_height_hack = delta - top; }
void Font::InitFont( void ) { Initialized = false; if( TTFont ) TTF_CloseFont( TTFont ); TTFont = TTF_OpenFont( Name.c_str(), PointSize ); if( ! TTFont ) { // FIXME: Use TTF_Error output? fprintf( stderr, "Can't open font file: %s\n", Name.c_str() ); return; } Height = TTF_FontHeight( TTFont ); Ascent = TTF_FontAscent( TTFont ); Descent = TTF_FontDescent( TTFont ); LineSkip = TTF_FontLineSkip( TTFont ); for( int i = 0; i < 256; i ++ ) { Glyphs[ i ].Pic = NULL; Glyphs[ i ].Tex = 0; } LoadedTime.Reset(); Initialized = true; }
static void cache_glyphs() { int top = 999; int bottom = -999; start_color(); for(int ch = 0; ch < 128; ch++) { for(int color = 0; color < 16; color++) { //I hate this kind of ternary use SDL_Surface * sglyph = (fontblending ? TTF_RenderGlyph_Blended : TTF_RenderGlyph_Solid)(font, ch, windowsPalette[color]); if(sglyph != NULL) { int minx, maxx, miny, maxy, advance; if(color==0 && 0 == TTF_GlyphMetrics(font, ch, &minx, &maxx, &miny, &maxy, &advance) ) { int t = TTF_FontAscent(font)-maxy; int b = t + sglyph->h; if(t < top) top = t; if(b > bottom) bottom = b; } glyph_height[ch] = sglyph->h; glyph_cache[ch][color] = SDL_CreateTextureFromSurface(renderer,sglyph); } SDL_FreeSurface(sglyph); } } int height = bottom - top; int delta = (fontheight - height) / 2; ttf_height_hack = delta - top; }
void GlyphFont::InitFont() { mTtfFont = TTF_OpenFont(mFilename, mPointSize); if(mTtfFont == NULL) printf("Can't open font file\n"); // 0 = TTF_STYLE_NORMAL // 1 = TTF_STYLE_BOLD // 2 = TTF_STYLE_ITALIC // 4 = TTF_STYLE_UNDERLINE // 8 = TTF_STYLE_STRIKETHROUGH TTF_SetFontStyle(mTtfFont, mStyle); mColor.r = (Uint8)(mRed * 255); mColor.g = (Uint8)(mGreen * 255); mColor.b = (Uint8)(mBlue * 255); mHeight = TTF_FontHeight(mTtfFont); mAscent = TTF_FontAscent(mTtfFont); mDescent = TTF_FontDescent(mTtfFont); mLineSkip = TTF_FontLineSkip(mTtfFont); for(int i = sMinGlyph; i <= sMaxGlyph; i++) { mGlyphs[i].Surface = NULL; mGlyphs[i].Texture = 0; } }
Bool renderText(GPU_Target* renderTarget, GC gc, int x, int y, const char* string) { LOG("Rendering text: '%s'\n", string); if (string == NULL || string[0] == '\0') { return True; } GraphicContext* gContext = GET_GC(gc); SDL_Color color = { GET_RED_FROM_COLOR(gContext->foreground), GET_GREEN_FROM_COLOR(gContext->foreground), GET_BLUE_FROM_COLOR(gContext->foreground), GET_ALPHA_FROM_COLOR(gContext->foreground), }; SDL_Surface* fontSurface = TTF_RenderUTF8_Blended(GET_FONT(gContext->font), string, color); if (fontSurface == NULL) { return False; } GPU_Image* fontImage = GPU_CopyImageFromSurface(fontSurface); SDL_FreeSurface(fontSurface); if (fontImage == NULL) { return False; } y -= TTF_FontAscent(GET_FONT(gContext->font)); GPU_Blit(fontImage, NULL, renderTarget, x + fontImage->w / 2, y + fontImage->h / 2); GPU_FreeImage(fontImage); GPU_Flip(renderTarget); return True; }
SDL_Rect FontInfo::calcUpdatedArea(int start_xy[2]) { SDL_Rect rect; if (tateyoko_mode == YOKO_MODE){ if (start_xy[1] == xy[1]){ rect.x = top_xy[0] + pitch_xy[0]*start_xy[0]/2; rect.w = pitch_xy[0]*(xy[0]-start_xy[0])/2+1; } else{ rect.x = top_xy[0]; rect.w = pitch_xy[0]*num_xy[0]; } rect.y = top_xy[1] + start_xy[1]*pitch_xy[1]/2; rect.h = pitch_xy[1]*(xy[1]-start_xy[1]+2)/2; if (ttf_font) rect.h += font_size_xy[1] - TTF_FontAscent((TTF_Font*)ttf_font); if (rubyon_flag) rect.h += pitch_xy[1] - font_size_xy[1]; } else{ rect.x = top_xy[0] + pitch_xy[0]*xy[0]/2; rect.w = pitch_xy[0]*(start_xy[0]-xy[0]+2)/2; if (rubyon_flag) rect.w += font_size_xy[0]-pitch_xy[0]; if (start_xy[0] == xy[0]){ rect.y = top_xy[1] + pitch_xy[1]*start_xy[1]/2; rect.h = pitch_xy[1]*(xy[1]-start_xy[1])/2+1; } else{ rect.y = top_xy[1]; rect.h = pitch_xy[1]*num_xy[1]; } num_xy[0] = (xy[0]-start_xy[0])/2+1; } return rect; }
void ONScripterLabel::drawGlyph( SDL_Surface *dst_surface, FontInfo *info, SDL_Color &color, char* text, int xy[2], bool shadow_flag, AnimationInfo *cache_info, SDL_Rect *clip, SDL_Rect &dst_rect ) { unsigned short unicode; if (IS_TWO_BYTE(text[0])){ unsigned index = ((unsigned char*)text)[0]; index = index << 8 | ((unsigned char*)text)[1]; unicode = onsLocaleConv( index ); } else{ if ((text[0] & 0xe0) == 0xa0 || (text[0] & 0xe0) == 0xc0) unicode = ((unsigned char*)text)[0] - 0xa0 + 0xff60; else unicode = text[0]; } int minx, maxx, miny, maxy, advanced; #if 0 if (TTF_GetFontStyle( (TTF_Font*)info->ttf_font ) != (info->is_bold?TTF_STYLE_BOLD:TTF_STYLE_NORMAL) ) TTF_SetFontStyle( (TTF_Font*)info->ttf_font, (info->is_bold?TTF_STYLE_BOLD:TTF_STYLE_NORMAL)); #endif TTF_GlyphMetrics( (TTF_Font*)info->ttf_font, unicode, &minx, &maxx, &miny, &maxy, &advanced ); //printf("min %d %d %d %d %d %d\n", minx, maxx, miny, maxy, advanced,TTF_FontAscent((TTF_Font*)info->ttf_font) ); SDL_Surface *tmp_surface = renderGlyph( (TTF_Font*)info->ttf_font, unicode ); bool rotate_flag = false; if ( info->getTateyokoMode() == FontInfo::TATE_MODE && IS_ROTATION_REQUIRED(text) ) rotate_flag = true; dst_rect.x = xy[0] + minx; dst_rect.y = xy[1] + TTF_FontAscent((TTF_Font*)info->ttf_font) - maxy; if ( rotate_flag ) dst_rect.x += miny - minx; if ( info->getTateyokoMode() == FontInfo::TATE_MODE && IS_TRANSLATION_REQUIRED(text) ){ dst_rect.x += info->font_size_xy[0]/2; dst_rect.y -= info->font_size_xy[0]/2; } if ( shadow_flag ){ dst_rect.x += shade_distance[0]; dst_rect.y += shade_distance[1]; } if ( tmp_surface ){ if (rotate_flag){ dst_rect.w = tmp_surface->h; dst_rect.h = tmp_surface->w; } else{ dst_rect.w = tmp_surface->w; dst_rect.h = tmp_surface->h; } if (cache_info) cache_info->blendBySurface( tmp_surface, dst_rect.x, dst_rect.y, color, clip, rotate_flag ); if (dst_surface) alphaBlend32( dst_surface, dst_rect, tmp_surface, color, clip, rotate_flag ); } }
void load_font(char *fname, int size) { char *p; free_font(); font=TTF_OpenFont(fname, size); if(!font) { printf("TTF_OpenFont: %s\n", TTF_GetError()); exit(3); } /* print some metrics and attributes */ printf("size : %d\n",size); printf("TTF_FontHeight : %d\n",TTF_FontHeight(font)); printf("TTF_FontAscent : %d\n",TTF_FontAscent(font)); printf("TTF_FontDescent : %d\n",TTF_FontDescent(font)); printf("TTF_FontLineSkip : %d\n",TTF_FontLineSkip(font)); printf("TTF_FontFaceIsFixedWidth: %d\n",TTF_FontFaceIsFixedWidth(font)); { char *str=TTF_FontFaceFamilyName(font); if(!str) str="(null)"; printf("TTF_FontFaceFamilyName : \"%s\"\n",str); } { char *str=TTF_FontFaceStyleName(font); if(!str) str="(null)"; printf("TTF_FontFaceStyleName : \"%s\"\n",str); } if(TTF_GlyphIsProvided(font,'g')) { int minx, maxx, miny, maxy, advance; TTF_GlyphMetrics(font,'g', &minx, &maxx, &miny, &maxy, &advance); printf("TTF_GlyphMetrics('g'):\n\tminx=%d\n\tmaxx=%d\n\tminy=%d\n\tmaxy=%d\n\tadvance=%d\n", minx, maxx, miny, maxy, advance); } else printf("TTF_GlyphMetrics('g'): unavailable in font!\n"); /* set window title and icon name, using filename and stuff */ p=strrchr(fname,'/'); if(!p) p=strrchr(fname,'\\'); if(!p) p=strrchr(fname,':'); if(!p) p=fname; else p++; /* cache new glyphs */ cache_glyphs(); }
float CText::GetAscent(FontType font, float size) { assert(font != FONT_BUTTON); CachedFont* cf = GetOrOpenFont(font, size); assert(cf != nullptr); Math::IntPoint wndSize; wndSize.y = TTF_FontAscent(cf->font); Math::Point ifSize = m_engine->WindowToInterfaceSize(wndSize); return ifSize.y; }
void Font::CalculateHeights() { height = TTF_FontHeight(font); ascent_height = TTF_FontAscent(font); int miny, maxy; TTF_GlyphMetrics(font, 'M', NULL, NULL, &miny, &maxy, NULL); capital_height = maxy - miny + 1; }
JNIEXPORT jint JNICALL Java_sdljava_x_swig_SWIG_1SDLTTFJNI_TTF_1FontAscent(JNIEnv *jenv, jclass jcls, jlong jarg1) { jint jresult = 0 ; TTF_Font *arg1 = (TTF_Font *) 0 ; int result; (void)jenv; (void)jcls; arg1 = *(TTF_Font **)&jarg1; result = (int)TTF_FontAscent(arg1); jresult = (jint)result; return jresult; }
// Get real text dimensions -- the textshape will completely contain the // rendered text but won't match its size. This function can be used to // get the true position and dimensions of the rendered text. // // The fifth argument, b, is the baseline of the text void TextShape::getTextDimensions(int *x, int *y, int *w, int *h, int *b, int *yOff) { if (textShapeFont[fontSize] == NULL) { textShapeFont[fontSize] = FONT_LoadTTF("FreeSans.ttf", fontSize); } assert(textShapeFont[fontSize] != NULL); int realH = 0; Uint16 *ch = unicodeStr; int overallMaxY = 0; while (*ch != '\0') { int minx, maxx, miny, maxy, advance; int err = TTF_GlyphMetrics(textShapeFont[fontSize], *ch, &minx, &maxx, &miny, &maxy, &advance); if (!err) { realH = std::max(realH, maxy - miny + 1); overallMaxY = std::max(overallMaxY, maxy); } else { printf("warning: TTF_GlyphMetrics returned an error\n"); } ch++; } int ascent = TTF_FontAscent(textShapeFont[fontSize]); int realYOffset = ascent - overallMaxY; // Can't get width from the individual glyphs due to kerning issues, // just call TTF_SizeUNICODE int textw, dummy; // Get text size: TTF_SizeUNICODE(textShapeFont[fontSize], unicodeStr, &textw, &dummy); if (x) *x = xpos + cxoff; if (y) *y = ypos + cyoff; if (w) *w = textw; if (h) *h = realH; if (b) *b = ypos + overallMaxY + cxoff; if (yOff) *yOff = realYOffset; }
KFontProperties::KFontProperties(const TTF_Font *_Font, const KFile *file, int ptSize) : fontPath(file->getAbsolutePath().c_str()), familyName(TTF_FontFaceFamilyName(_Font)), styleName(TTF_FontFaceStyleName(_Font)), ttf_Style(TTF_GetFontStyle(_Font)), height(TTF_FontHeight(_Font)), ascent(TTF_FontAscent(_Font)), descent(TTF_FontDescent(_Font)), lineSkip(TTF_FontLineSkip(_Font)), faces(TTF_FontFaces(_Font)), monospace(TTF_FontFaceIsFixedWidth(_Font)), firstGlyph(getFirstGlyph(_Font)), lastGlyph(getLastGlyph(_Font)), totalGlyphs(getTotalGlyphs(_Font)), glyphRanges(getRanges(_Font)), pointSize(ptSize) { }
static void OutputChar(Uint16 t, int x, int y, unsigned char color) { color &= 0xf; SDL_Surface * glyph = t<0x80?glyph_cache[t][color]:(fontblending?TTF_RenderGlyph_Blended:TTF_RenderGlyph_Solid)(font, t, windowsPalette[color]); if(glyph) { int minx=0, maxy=0, dx=0, dy = 0; if( 0==TTF_GlyphMetrics(font, t, &minx, NULL, NULL, &maxy, NULL)) { dx = minx; dy = TTF_FontAscent(font)-maxy+ttf_height_hack; SDL_Rect rect; rect.x = x+dx; rect.y = y+dy; rect.w = fontwidth; rect.h = fontheight; SDL_BlitSurface(glyph, NULL, screen, &rect); } if(t>=0x80) SDL_FreeSurface(glyph); } }
bool FontTTF::load(std::string fileName, int size) { cleanUp(); _font = TTF_OpenFont( fileName.c_str(), size ); if (NULL == _font) std::cerr << "Failed to load font " << fileName << ". Cannot start." << std::endl; else // _height = size; //calc_text_metrics("X")._y; // _height = calc_text_metrics("A")._max._y; // _height = TTF_FontHeight(_font); _height = TTF_FontAscent(_font); /* int minx,maxx,miny,maxy,advance; if(TTF_GlyphMetrics(_font,'A',&minx,&maxx,&miny,&maxy,&advance)==-1) return 0; _height = maxy;// - miny; */ _init = (_font != NULL); return _init; }
static void OutputChar(char t, int x, int y, int n, unsigned char color) { unsigned char ch = t & 0x7f; color &= 0xf; SDL_Surface * glyph = glyph_cache[ch][color]; if(glyph) { int minx=0, maxy=0, dx=0, dy = 0; if( 0==TTF_GlyphMetrics(font, ch, &minx, NULL, NULL, &maxy, NULL)) { dx = minx; dy = TTF_FontAscent(font)-maxy+ttf_height_hack; SDL_Rect rect; rect.x = x+dx; rect.y = y+dy; rect.w = fontwidth; rect.h = fontheight; SDL_BlitSurface(glyph, NULL, screen, &rect); } } }
static void OutputFontChar(Uint16 t, int x, int y, unsigned char color) { color &= 0xf; bool created = false; SDL_Texture * glyph; int height = 0; if(t < 0x80) { glyph = glyph_cache[t][color]; height = glyph_height[t]; } else { //create the texture instead SDL_Surface *sglyph = (fontblending ? TTF_RenderGlyph_Blended : TTF_RenderGlyph_Solid) (font, t, windowsPalette[color]); glyph = SDL_CreateTextureFromSurface(renderer,sglyph); height = sglyph->h; SDL_FreeSurface(sglyph); created = true; } if(glyph) { int minx = 0, miny = 0, maxy = 0, dx = 0, dy = 0; if( 0 == TTF_GlyphMetrics(font, t, &minx, NULL, &miny, &maxy, NULL)) { dx = minx; dy = TTF_FontAscent(font) - maxy + ttf_height_hack; SDL_Rect rect; rect.x = x + dx; rect.y = y + dy; //these are not fontwidth/fontheight... rect.w = fontwidth; rect.h = height; SDL_RenderCopy(renderer,glyph,NULL,&rect); } if(created) { SDL_DestroyTexture(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()
// // Load a new font and create textures for each glyph // font *ttf_new (const char *name, int pointSize, int style) { uint8 c; font *f; f = (fontp)zalloc(sizeof(*f)); if (!f) { return (NULL); } f->name = strdup(name); f->ttf = TTF_OpenFont(name, pointSize); if (!f->ttf) { DIE("cannot open font file %s", name); } f->foreground.r = 255; f->foreground.g = 255; f->foreground.b = 255; f->background.r = 0; f->background.g = 0; f->background.b = 0; TTF_SetFontStyle(f->ttf, style); TTF_SetFontOutline(f->ttf, 0.5); f->height = TTF_FontHeight(f->ttf); f->ascent = TTF_FontAscent(f->ttf); f->descent = TTF_FontDescent(f->ttf); f->lineSkip = TTF_FontLineSkip(f->ttf); for (c = TTF_GLYPH_MIN; c < TTF_GLYPH_MAX; c++) { ttf_create_tex_from_char(f, c); } return (f); }
void FontTTF::loadMetrics(TTF_Font *font) { _cellHeight = TTF_FontHeight(font); _cellWidth = 0; int x1, x2, y1, y2, advance; for( int i = 0; i < 256; ++i ) { TTF_GlyphMetrics(font, static_cast<Uint16>(i), &x1, &x2, &y1, &y2, &advance); // Only handle visible characters (>32) and the 'space' character (32). _fontWidth[i] = i >= 32 ? advance : 0; if(_fontWidth[i] > _cellWidth) { _cellWidth = advance; } } // Set a tab to be the width of 4 spaces. _fontWidth[9] = _fontWidth[32] * 4; _fontAscent = TTF_FontAscent(font); _fontDescent = TTF_FontDescent(font); _fontHeight = _fontAscent - _fontDescent; _lineSkip = TTF_FontLineSkip(font); }
Font::Font(const std::string& path, int size) { TTF_Font* font = TTF_OpenFont(path.c_str(), size); if (!font) { fatalError("Failed to open font '" + path + "'."); } SDL_Color color {255, 255, 255, 255}; SDL_Surface* surfaces [NUM_GLYPHS]; for (int i = 0; i < NUM_GLYPHS; i++) { char c = FIRST_CHAR + i; TTF_GlyphMetrics( font, c, &glyph_metrics_map_[i].min_x, &glyph_metrics_map_[i].max_x, &glyph_metrics_map_[i].min_y, &glyph_metrics_map_[i].max_y, &glyph_metrics_map_[i].advance); surfaces[i] = TTF_RenderGlyph_Blended(font, c, color); } int font_height = TTF_FontHeight(font); int font_offset = font_height - TTF_FontAscent(font); int num_glyphs_per_row = 16; int num_rows = (NUM_GLYPHS - 1) / num_glyphs_per_row + 1; int max_row_width = 0; for (int i = 0; i < num_rows; i++) { int row_width = 0; for (int j = 0; j < num_glyphs_per_row; j++) { int index = i * num_glyphs_per_row + j; if (index >= NUM_GLYPHS) break; row_width += surfaces[index]->w; } if (row_width > max_row_width) max_row_width = row_width; } int atlas_height = num_rows * font_height; int atlas_width = max_row_width; int cursor_x = 0; int cursor_y = 0; int bytes_per_pixel = 4; std::vector<uint8_t> atlas_pixels (bytes_per_pixel * atlas_height * atlas_width); for (int i = 0; i < num_rows; i++) { for (int j = 0; j < num_glyphs_per_row; j++) { int index = i * num_glyphs_per_row + j; if (index >= NUM_GLYPHS) break; SDL_Surface* surface = surfaces[index]; for (int k = 0; k < font_height; k++) { for (int l = 0; l < surface->w; l++) { int atlas_index = bytes_per_pixel * ((cursor_y + k) * atlas_width + cursor_x + l); int surface_index = bytes_per_pixel * ((surface->h - k - 1) * surface->w + l); for (int m = 0; m < bytes_per_pixel; m++) { atlas_pixels[atlas_index + m] = reinterpret_cast<uint8_t*>(surface->pixels)[surface_index + m]; } } } GlyphMetrics& metrics = glyph_metrics_map_[index]; GlyphBound& bound = glyph_bound_map_[index]; bound.min_s = double(cursor_x + metrics.min_x) / atlas_width; bound.max_s = double(cursor_x + metrics.max_x) / atlas_width; bound.min_t = double(cursor_y + font_offset + metrics.min_y) / atlas_height; bound.max_t = double(cursor_y + font_offset + metrics.max_y) / atlas_height; cursor_x += surface->w; } cursor_x = 0; cursor_y += font_height; } for (int i = 0; i < NUM_GLYPHS; i++) { SDL_FreeSurface(surfaces[i]); } TTF_CloseFont(font); glGenTextures(1, &atlas_); glBindTexture(GL_TEXTURE_2D, atlas_); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, atlas_width, atlas_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, atlas_pixels.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); }
void GM_Debug::renderScene() { if(background) background->Blit(0,0,0,0,background->getBasicWidth(),background->getBasicHeight(),glictGlobals.w, glictGlobals.h); if(spr) spr->Blit(50,50); if(thing) thing->Blit(100,50); if(background) background->Blit(150,50,125,51,85,136,32,48); /* int xs = px - mapw/2; int ys = py - maph/2; int xe = px + mapw/2; int ye = py + maph/2; if (map[0]) map[0]->Blit(0,0, xs%256, ys%256, 256-(xs%256), 256-(ys%256)); if (map[1]) map[1]->Blit(256-(xs%256),0, 0, ys%256, mapw-(256-(xs%256)), 256-(ys%256)); if (map[2]) map[2]->Blit(0,256-(ys%256), xs%256, 0, 256-(xs%256), maph-(256-(ys%256))); if (map[3]) map[3]->Blit(256-(xs%256),256-(ys%256), 0, 0, mapw-(256-(xs%256)), maph-(256-(ys%256))); */ GM_Debug *gd = (GM_Debug*)g_game; a.renderSelf(700,0,256,256,Position(gd->px, gd->py, gd->pz)); /* std::stringstream testchar; testchar << (char)('u'+32); for(int i = 0; i < 255; i++) { g_engine->drawText(testchar.str().c_str(), "system", 0+(i%8)*12,300+(i/8)*12, i); } */ //desktop.RememberTransformations(); desktop.Paint(); #ifdef SDLTTF_EXPERIMENT if (font) { SDL_Surface* glyph = NULL; SDL_Color forecol, backcol; forecol.r = 255; forecol.g = 255; forecol.b = 255; backcol.r = 0; backcol.g = 0; backcol.b = 0; SDL_SetClipRect(g_engine->m_screen, NULL); int YOffset = TTF_FontAscent(font); // Actually a baseline for (int i = 32; i < 256; i++) { int minx, maxx, miny, maxy, advance; glyph = TTF_RenderGlyph_Solid( font, i, forecol);//backcol ); // solid or shaded; shaded uses backcol, solid doesnt TTF_GlyphMetrics(font, i, &minx, &maxx, &miny, &maxy, &advance); SDL_Rect src = {0, 0, glyph->w, glyph->h}; SDL_Rect dest = {((i - 32) % 32)*8 + minx, ((i - 32) / 32)*16 + YOffset-maxy, glyph->w, glyph->h}; SDL_BlitSurface(glyph, &src, g_engine->m_screen, &dest); SDL_FreeSurface(glyph); } } #endif }
XFontStruct* XLoadQueryFont(Display* display, _Xconst char* name) { // https://tronche.com/gui/x/xlib/graphics/font-metrics/XLoadQueryFont.html Font fontId = XLoadFont(display, name); if (fontId == None) { return NULL; } TTF_Font* font = GET_FONT(fontId); SET_X_SERVER_REQUEST(display, X_QueryFont); XFontStruct* fontStruct = malloc(sizeof(XFontStruct)); if (fontStruct == NULL) { handleOutOfMemory(0, display, 0, 0); TTF_CloseFont(font); return NULL; } fontStruct->fid = fontId; fontStruct->ascent = TTF_FontAscent(font); fontStruct->descent = abs(TTF_FontDescent(font)); fontStruct->per_char = NULL; unsigned int numChars = 0; unsigned int i; for (i = 0; i < 65536 /* 2^16 */; i++) { if (TTF_GlyphIsProvided(font, (Uint16) i)) { if (numChars == 0) { fontStruct->min_char_or_byte2 = i; } fontStruct->max_char_or_byte2 = i; numChars++; } } // if (numChars >= 256) { // fontStruct->min_byte1 = fontStruct->min_char_or_byte2 / 256; // fontStruct->max_byte1 = fontStruct->max_char_or_byte2 / 256; // fontStruct->min_char_or_byte2 = 0; // } else { fontStruct->min_byte1 = 0; fontStruct->max_byte1 = 0; // } // TODO: This is debugging fontStruct->max_char_or_byte2 = 255; // Build per_char int monospace = TTF_FontFaceIsFixedWidth(font); XCharStruct charStruct; if (!monospace) { fontStruct->per_char = malloc(sizeof(XCharStruct) * numChars); if (fontStruct->per_char == NULL) { handleOutOfMemory(0, display, 0, 0); XFreeFont(display, fontStruct); return NULL; } charStruct = fontStruct->per_char[0]; } if (fillXCharStruct(font, fontStruct->min_char_or_byte2, &charStruct) == False) { XFreeFont(display, fontStruct); return NULL; } fontStruct->max_bounds = charStruct; fontStruct->min_bounds = charStruct; if (monospace) { fontStruct->per_char = NULL; } else { int counter = 1; for (i = fontStruct->min_char_or_byte2 + 1; i < 65536 /* 2^16 */; ++i) { if (TTF_GlyphIsProvided(font, (Uint16) i)) { charStruct = fontStruct->per_char[counter]; if (fillXCharStruct(font, i, &charStruct) == False) { XFreeFont(display, fontStruct); return NULL; } // I think rbearing (aka. advance) is the value that matters here if (fontStruct->max_bounds.rbearing < charStruct.rbearing) { fontStruct->max_bounds = charStruct; } else if (fontStruct->min_bounds.rbearing > charStruct.rbearing) { fontStruct->max_bounds = charStruct; } counter++; } } } return fontStruct; }
int main(int argc, char* argv[]) { if ( argc < 4 ) { fprintf(stderr, "usage: tool_font filename.ttf chars.txt ptsize <style> <supersample>\n"); return -1; } char szFont[256]; strcpy(szFont, argv[1]); *strstr(szFont, ".ttf") = 0; int nFontSize = atol(argv[3]); int nStyle = TTF_STYLE_NORMAL; if ( argc > 3 ) { for ( int i = 0 ; argv[4][i] != 0 ; i++ ) { switch ( argv[4][i] ) { case 'b': nStyle |= TTF_STYLE_BOLD; break; case 'i': nStyle |= TTF_STYLE_ITALIC; break; case 'u': nStyle |= TTF_STYLE_UNDERLINE; break; } } } float fScale = 1.0f; if ( argc > 5 ) { fScale = 1.0f/atof(argv[6]); } SDL_Init(SDL_INIT_VIDEO); TTF_Init(); TTF_Font* pFont = TTF_OpenFont(argv[1], nFontSize/fScale); if ( !pFont ) { fprintf(stderr, "could not open %s @ %d points\n", argv[1], nFontSize); return -1; } int nAscent = TTF_FontAscent(pFont); int nDescent = TTF_FontDescent(pFont); int nHeight = TTF_FontHeight(pFont); char szStyle[4] = { 0 }; char* pchStyle = szStyle; if ( nStyle & TTF_STYLE_BOLD ) *pchStyle++ = 'b'; if ( nStyle & TTF_STYLE_ITALIC ) *pchStyle++ = 'i'; if ( nStyle & TTF_STYLE_UNDERLINE ) *pchStyle++ = 'u'; TTF_SetFontStyle(pFont, nStyle); char achGlyphs[1024]; int cGlyphs = 0; FILE* fpChars = fopen(argv[2], "r"); while ( EOF != (achGlyphs[cGlyphs++] = fgetc(fpChars)) ); fclose(fpChars); cGlyphs--; SDL_Rect* aRects = new SDL_Rect[cGlyphs]; SDL_Surface** apSurfaces = new SDL_Surface*[cGlyphs]; for ( int iGlyph = 0 ; iGlyph < cGlyphs ; ++iGlyph ) { SDL_Color color = { 255, 255, 255, 0 }; char szGlyph[2] = { 0 }; szGlyph[0] = achGlyphs[iGlyph]; apSurfaces[iGlyph] = TTF_RenderText_Blended(pFont, szGlyph, color); // char szFile[128]; // sprintf(szFile, "textures/fonts/%s/%d.raw", argv[1], szGlyph[0]); // FILE* fp = fopen(szFile, "wb"); // fwrite(apSurfaces[iGlyph]->pixels, apSurfaces[iGlyph]->pitch*apSurfaces[iGlyph]->h, 1, fp); // fclose(fp); } struct DIMS { int w, h; }; DIMS aDims[] = { 64, 64, 64, 128, 64, 256, 128, 64, 128, 128, 128, 256, 256, 64, 256, 128, 256, 256, 64, 512, 128, 512, 256, 512, 512, 64, 512, 128, 512, 256, 512, 512, 64, 1024, 128, 1024, 256, 1024, 256, 1024, 512, 1024, 1024, 64, 1024, 128, 1024, 256, 1024, 512, 1024, 1024, 64, 2048, 128, 2048, 256, 2048, 512, 2048, 1024, 2048, 2048, 64, 2048, 128, 2048, 256, 2048, 512, 2048, 1024, 2048, 2048, /* 512, 64, 512, 128, 512, 256, 512, 512, 64, 512, 128, 512, 256, 512, 1024, 64, 1024, 128, 1024, 256, 1024, 512, 64, 1024, 128, 1024, 256, 1024, 512, 1024, 2048, 64, 2048, 128, 2048, 256, 2048, 1024, 2048, 2048, 64, 2048, 128, 2048, 256, 2048, 512, 2048, 1024, 2048 */ }; int cDims = sizeof(aDims)/sizeof(DIMS); for ( int iDims = 0 ; iDims < cDims ; ++iDims ) { int nWidth = aDims[iDims].w; int nHeight = aDims[iDims].h; SDL_Surface* pSurfaceGeneric = SDL_CreateRGBSurface(SDL_SWSURFACE, nWidth, nHeight, 32, 0, 0, 0, 0); SDL_Surface* pSurface = SDL_ConvertSurface(pSurfaceGeneric, apSurfaces[0]->format, 0); SDL_FillRect(pSurface, NULL, SDL_MapRGBA(pSurface->format, 0,0,0,0)); bool* aabyUsage = new bool[nHeight*nWidth]; memset(aabyUsage, 0, nHeight*nWidth*sizeof(bool)); bool bFit = true; for ( int iGlyph = 0 ; iGlyph < cGlyphs ; ++iGlyph ) { if ( !Fit(aabyUsage, pSurface, apSurfaces[iGlyph], &aRects[iGlyph], fScale) ) { bFit = false; break; } } if ( bFit ) { fprintf(stderr, "glyphs fit into %d x %d texture\n", nWidth, nHeight); char szFile[256]; sprintf(szFile, "textures/fonts/%s%d%s.png", szFont, nFontSize, szStyle); for ( int y = 0 ; y < pSurface->h ; ++y ) { for ( int x = 0 ; x < pSurface->w ; ++x ) { unsigned char r = ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 0]; unsigned char g = ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 1]; unsigned char b = ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 2]; unsigned char a = (r+g+b)/3; r = g = b = 255; ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 0] = r; ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 1] = g; ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 2] = b; ((unsigned char*)pSurface->pixels)[x*4 + y*pSurface->w*4 + 3] = a; } } ILuint iImage = 0; ilInit(); ilGenImages(1, &iImage); ilBindImage(iImage); ilTexImage(pSurface->w, pSurface->h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pSurface->pixels); // ilConvertImage(IL_LUMINANCE, IL_UNSIGNED_BYTE); iluFlipImage(); iluImageParameter(ILU_FILTER, ILU_SCALE_LANCZOS3); iluScale(pSurface->w*fScale, pSurface->h*fScale, 1); ilSaveImage(szFile); int nDescent = TTF_FontDescent(pFont); char szFontFile[256]; sprintf(szFontFile, "fonts/%s%d%s.font", szFont, nFontSize, szStyle); FILE* fp = fopen(szFontFile, "w"); fprintf(fp, "<font name=\"%s\" height=\"%d\" lineskip=\"%d\" shader=\"%s,srcalpha,invsrcalpha\">\n", szFont, int(TTF_FontHeight(pFont)*fScale), int(TTF_FontLineSkip(pFont)*fScale), szFile); for ( int iGlyph = 0 ; iGlyph < cGlyphs ; ++iGlyph ) { int xmin, xmax, ymin, ymax, adv; TTF_GlyphMetrics(pFont, achGlyphs[iGlyph], &xmin, &xmax, &ymin, &ymax, &adv); fprintf(fp, "%c<glyph ascii=\"%d\" adv=\"%d\" dims=\"%d,%d\" origin=\"%d,%d\" u0=\"%f\" v0=\"%f\" u1=\"%f\" v1=\"%f\"/>\n", 9, achGlyphs[iGlyph], int(adv*fScale), int(aRects[iGlyph].w*fScale), int(aRects[iGlyph].h*fScale), int(xmin*fScale), int(-nDescent*fScale), float(aRects[iGlyph].x)/float(pSurface->w), float(aRects[iGlyph].y)/float(pSurface->h), float(aRects[iGlyph].x+aRects[iGlyph].w)/float(pSurface->w), float(aRects[iGlyph].y+aRects[iGlyph].h)/float(pSurface->h)); } fprintf(fp, "</font>\n"); fclose(fp); // FILE* fp = fopen("textures/fonts/blockup.raw", "wb"); // fwrite(pSurface->pixels, pSurface->pitch*pSurface->h, 1, fp); // fclose(fp); return 0; } delete [] aabyUsage; SDL_FreeSurface(pSurface); SDL_FreeSurface(pSurfaceGeneric); } return 0; }
static void track_baseline(const struct rect *rect, const TTF_Font *a, struct rect *aligned, const TTF_Font *b) { split(*rect, pixels(from_top(TTF_FontAscent(a) - TTF_FontAscent(b), 0)), NULL, aligned); }
/* * create_font */ int create_font(char *filename, FONT **font, int size, int style, SDL_Color color) { TTF_Font* ttffont; SDL_Surface* character_surface; int ret_code = BUILD_FONT_OK; int rc; Uint16 ii; /* * Allocate the memory required for the font object. */ (*font) = (FONT *) DT_MALLOC(sizeof(FONT)); /* * Set the font attributes. */ memcpy(&((*font)->color), &color, sizeof(SDL_Color)); (*font)->pointsize = size; (*font)->style = style; /* * The font loading may fail if the file does not exist or permissions are * incorrect etc. */ ttffont = TTF_OpenFont(filename, (*font)->pointsize); if (ttffont == NULL) { DT_DEBUG_LOG("Error opening font (%s): %s\n", filename, TTF_GetError()); ret_code = BUILD_FONT_LOAD_FAIL; goto EXIT_LABEL; } /* * Set the style of the font to whatever we passed in. */ TTF_SetFontStyle(ttffont, (*font)->style); /* * Retrieve the font information to store in our font structure. */ (*font)->ascent = TTF_FontAscent(ttffont); (*font)->descent = TTF_FontDescent(ttffont); (*font)->height = TTF_FontHeight(ttffont); (*font)->lineskip = TTF_FontLineSkip(ttffont); /* * For each possible glyph, attempt to load the font character and create a * texture for it. If any of these fail we attempt to close down gracefully * and exit the function. */ for (ii = ' '; ii <= '~'; ii++) { character_surface = TTF_RenderGlyph_Blended(ttffont, ii, (*font)->color); if (NULL == character_surface) { DT_DEBUG_LOG("Error rendering glyph %c whilst creating font (%s): %s\n", (char) ii, filename, TTF_GetError()); ret_code = BUILD_FONT_RENDER_FAIL; goto EXIT_LABEL; } /* * Retrieve the metric info from the font object and store it in our local * structure. */ TTF_GlyphMetrics(ttffont, ii, &((*font)->glyphs[ii].minx), &((*font)->glyphs[ii].maxx), &((*font)->glyphs[ii].miny), &((*font)->glyphs[ii].maxy), &((*font)->glyphs[ii].advance)); /* * This function can fail if opengl cannot allocate any more memory for * textures. */ rc = SDL_GL_LoadTexture(character_surface, &((*font)->glyphs[ii].texid), false); if (LOAD_TEXTURE_OK != rc) { DT_DEBUG_LOG("Failed creating texture for glyph %c from font %s\n", (char) ii, TTF_GetError()); SDL_FreeSurface(character_surface); ret_code = BUILD_FONT_CREATE_TEXTURE_FAIL; goto EXIT_LABEL; } /* * Set the texture coordinates for the glyph (note this is the same for all * glyphs). */ (*font)->glyphs[ii].texcoord[0] = 0.0f; (*font)->glyphs[ii].texcoord[1] = 0.0f; (*font)->glyphs[ii].texcoord[2] = 1.0f; (*font)->glyphs[ii].texcoord[3] = 1.0f; /* * The surface used for that character is no longer required. */ SDL_FreeSurface(character_surface); } EXIT_LABEL: if (NULL != ttffont) { TTF_CloseFont(ttffont); } return ret_code; }