void update_infos() { //base y position of the text int base_y = 0; //height of a line of text with the current font. int line_height = TTF_FontLineSkip(font); //buffer to hold the current textto be drawn char buf[TEXT_BUF_SIZE]; //retrieve navdata one by one int bat = jakopter_com_read_int(com_in, 0); //and format it for textual display snprintf(buf, TEXT_BUF_SIZE, "Battery : %d%%", bat); buf[TEXT_BUF_SIZE-1] = '\0'; //finally, print it onto a texture using SDL_ttf graphs[0].tex = video_make_text(buf, &graphs[0].pos.w, &graphs[0].pos.h); //and set its draw position accordingly graphs[0].pos.x = 0; graphs[0].pos.y = base_y; //go to a new line base_y += line_height; int alt = jakopter_com_read_int(com_in, 4); snprintf(buf, TEXT_BUF_SIZE, "Altitude : %d", alt); buf[TEXT_BUF_SIZE-1] = '\0'; graphs[1].tex = video_make_text(buf, &graphs[1].pos.w, &graphs[1].pos.h); graphs[1].pos.x = 0; graphs[1].pos.y = base_y; //update pitch, roll, yaw and speed pitch = jakopter_com_read_float(com_in, 8); roll = jakopter_com_read_float(com_in, 12); yaw = jakopter_com_read_float(com_in, 16); speed = jakopter_com_read_float(com_in, 20); }
int BEE::Font::draw_fast(int x, int y, std::string text, RGBA color) { if (is_loaded) { std::map<int,std::string> lines = handle_newlines(text); if (lineskip == 0) { if (is_sprite) { lineskip = sprite_font->get_height(); } else { lineskip = TTF_FontLineSkip(font); } } int r = 0; for (auto& l : lines) { int ri = draw_fast_internal(x, y+lineskip*l.first, l.second, color); if (ri > r) { r = ri; } } return r; } if (!has_draw_failed) { game->messenger_send({"engine", "font"}, BEE_MESSAGE_WARNING, "Failed to draw text with \"" + name + "\" because it is not loaded"); has_draw_failed = true; } return 1; }
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; }
int BEE::Font::get_lineskip_default() { if (is_loaded) { return TTF_FontLineSkip(font); } game->messenger_send({"engine", "font"}, BEE_MESSAGE_WARNING, "Failed to get the default lineskip for \"" + name + "\" becuase it is not loaded"); return -1; }
TextData* BEE::Font::draw(int x, int y, std::string text, RGBA color) { if (is_loaded) { TextData *r = nullptr, *textdata = nullptr; std::map<int,std::string> lines = handle_newlines(text); if (lineskip == 0) { lineskip = TTF_FontLineSkip(font); } for (auto& l : lines) { r = draw_internal(x, y+lineskip*l.first, l.second, color); if (r != nullptr) { if (textdata == nullptr) { textdata = r; } else { textdata->sprite.insert(std::make_pair(textdata->sprite.size(), r->sprite[0])); delete r; } } } return textdata; } if (!has_draw_failed) { game->messenger_send({"engine", "font"}, BEE_MESSAGE_WARNING, "Failed to draw text with \"" + name + "\" because it is not loaded"); has_draw_failed = true; } return nullptr; }
/******************************************************************************\ Loads the font, properly scaled and generates an error message if something goes wrong. For some reason, SDL_ttf returns a line skip that is one pixel shy of the image height returned by TTF_RenderUTF8_Blended() so we account for that here. \******************************************************************************/ static void load_font(r_font_t font, c_var_t *var, int size) { int points; points = (int)ceilf(size * r_scale_2d); if (points < FONT_SIZE_MIN) points = FONT_SIZE_MIN; C_zero(fonts + font); fonts[font].ttf_font = TTF_OpenFont(var->value.s, points); if (!fonts[font].ttf_font) { C_warning("Failed to load font '%s' (%d -> %d pt)", var->value.s, size, points); /* Fallback to the stock font file */ fonts[font].ttf_font = TTF_OpenFont(var->stock.s, points); if (!fonts[font].ttf_font) C_error("Failed to load font '%s' (%d -> %d pt) and " "stock font '%s'", var->value.s, size, points, var->stock.s); } fonts[font].height = TTF_FontHeight(fonts[font].ttf_font); fonts[font].line_skip = TTF_FontLineSkip(fonts[font].ttf_font) + 1; /* SDL_ttf won't tell us the width of the widest glyph directly so we assume it is the width of 'W' */ fonts[font].width = (int)R_font_size(font, "W").x; }
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; } }
void Text::setText(std::string text){ myText = text; int n = 0; std::vector<std::string> textLines; std::string substring = text; while(n != std::string::npos){ n = substring.find('\n', 0); textLines.push_back(substring.substr(0, n)); substring = substring.substr(n + 1, std::string::npos); } numLines = textLines.size(); image.clear(); for(unsigned int i = 0; i < textLines.size(); i++) image.push_back(TTF_RenderText_Blended(font, textLines.at(i).c_str(), color)); int wtemp, w = 0; for(unsigned int i = 0; i < textLines.size(); i++){ TTF_SizeText(this->font, textLines.at(i).c_str(), &wtemp, NULL); if(wtemp > w) w = wtemp; } int h = 10; lineSkip = TTF_FontLineSkip(font); h = (textLines.size() - 1) * lineSkip + h; setDimensions(w, h); }
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; } }
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(...)
SDLFontEngine::SDLFontEngine() : FontEngine(), active_font(NULL) { // Initiate SDL_ttf if(!TTF_WasInit() && TTF_Init()==-1) { logError("SDLFontEngine: TTF_Init: %s", TTF_GetError()); Exit(2); } // load the fonts // @CLASS SDLFontEngine: Font settings|Description of engine/font_settings.txt FileParser infile; if (infile.open("engine/font_settings.txt")) { while (infile.next()) { if (infile.new_section) { SDLFontStyle f; f.name = infile.section; font_styles.push_back(f); } if (font_styles.empty()) continue; SDLFontStyle *style = &(font_styles.back()); if ((infile.key == "default" && style->path == "") || infile.key == LANGUAGE) { // @ATTR $STYLE.default, $STYLE.$LANGUAGE|filename (string), point size (integer), blending (boolean)|Filename, point size, and blend mode of the font to use for this language. $STYLE can be something like "font_normal" or "font_bold". $LANGUAGE can be a 2-letter region code. style->path = popFirstString(infile.val); style->ptsize = popFirstInt(infile.val); style->blend = toBool(popFirstString(infile.val)); style->ttfont = TTF_OpenFont(mods->locate("fonts/" + style->path).c_str(), style->ptsize); if(style->ttfont == NULL) { logError("FontEngine: TTF_OpenFont: %s", TTF_GetError()); } else { int lineskip = TTF_FontLineSkip(style->ttfont); style->line_height = lineskip; style->font_height = lineskip; } } } infile.close(); } // set the font colors Color color; if (infile.open("engine/font_colors.txt")) { while (infile.next()) { // @ATTR menu_normal, menu_bonus, menu_penalty, widget_normal, widget_disabled|r (integer), g (integer), b (integer)|Colors for menus and widgets // @ATTR combat_givedmg, combat_takedmg, combat_crit, combat_buff, combat_miss|r (integer), g (integer), b (integer)|Colors for combat text // @ATTR requirements_not_met, item_bonus, item_penalty, item_flavor|r (integer), g (integer), b (integer)|Colors for tooltips // @ATTR item_$QUALITY|r (integer), g (integer), b (integer)|Colors for item quality. $QUALITY should match qualities used in items/items.txt color_map[infile.key] = toRGB(infile.val); } infile.close(); } // Attempt to set the default active font setFont("font_regular"); if (!active_font) { logError("FontEngine: Unable to determine default font!"); Exit(1); } }
int GW_PlatformSDL::text_fontheight() { #ifndef GW_NO_SDL_TTF return TTF_FontLineSkip(font_); #else return 1; #endif }
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(); }
int TTFS_FontLineSkipSecure(TTF_Font *font) { int lineSkip; if (!WaitForYourTurn()) return -1; lineSkip = TTF_FontLineSkip(font); YouAreOver(); return lineSkip; }
JNIEXPORT jint JNICALL Java_sdljava_x_swig_SWIG_1SDLTTFJNI_TTF_1FontLineSkip(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_FontLineSkip(arg1); jresult = (jint)result; return jresult; }
FontEngine::FontEngine() { font_pt = 10; // Initiate SDL_ttf if(!TTF_WasInit() && TTF_Init()==-1) { printf("TTF_Init: %s\n", TTF_GetError()); exit(2); } // load the font string font_path; FileParser infile; if (infile.open(PATH_DATA + "engine/font_settings.txt")) { while (infile.next()) { if (infile.key == "font_regular"){ font_path = infile.val; } if (infile.key == "ptsize"){ font_pt = atoi(infile.val.c_str()); } } } font_path = PATH_DATA + "fonts/" + font_path; font = TTF_OpenFont(font_path.c_str(), font_pt); if(!font) printf("TTF_OpenFont: %s\n", TTF_GetError()); // calculate the optimal line height line_height = TTF_FontLineSkip(font); font_height = TTF_FontHeight(font); // set the font colors SDL_Color white = {255,255,255}; SDL_Color red = {255,0,0}; SDL_Color green = {0,255,0}; SDL_Color blue = {0,0,255}; SDL_Color grey = {128,128,128}; SDL_Color black = {0,0,0}; colors[FONT_WHITE] = white; colors[FONT_RED] = red; colors[FONT_GREEN] = green; colors[FONT_BLUE] = blue; colors[FONT_GREY] = grey; colors[FONT_BLACK] = black; }
void hardwareInit() { if(SDL_Init(SDL_INIT_VIDEO)<0) { exit(1); } atexit(SDL_Quit); if(TTF_Init() < 0) { exit(2); } atexit(TTF_Quit); font = TTF_OpenFont("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 8*2); if(!font) { exit(3); } printf("The font line skip is: %d\n", TTF_FontLineSkip(font)); Uint32 flags = SDL_SWSURFACE; screen = SDL_SetVideoMode(160*2, 80*2, 16, flags); }
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) { }
void GUI::TextButton::Draw() { SDL_Rect rect = {x, y, w, h}; ensure_SDL_BlitSurface(m_bgs, NULL, screen, &rect); if(m_borders) { Uint32 bcolour = has_focus() ? SDL_MapRGB(screen->format, 255, 255, 0) : SDL_MapRGB(screen->format, 255, 255, 255); SDL_Rect ra = {x,y,w,1}, rb = {x,y,1,h}, rc = {x,y+h,w,1}, rd = {x+w,y,1,h+1}; ensure_SDL_FillRect(screen, &ra, bcolour); ensure_SDL_FillRect(screen, &rb, bcolour); ensure_SDL_FillRect(screen, &rc, bcolour); ensure_SDL_FillRect(screen, &rd, bcolour); } rect.w = 0; rect.h = 0; int hoff = (h - TTF_FontLineSkip(m_font)) / 2; int width = FontStuff::TextWidth(m_font, m_text); switch(m_align) { case LEFT: rect.x = x + hoff; rect.y = y + hoff; break; case CENTER: rect.x = x + (w - width) / 2; rect.y = y + hoff; break; case RIGHT: rect.x = (x + w) - (width + hoff); rect.y = y + hoff; break; } FontStuff::BlitText(screen, rect, m_font, m_fgc, m_text); }
static void GUI_SetTextRecursive(GUI_Window w, const char * text, int line_number) { SDL_Surface * text_line = NULL; SDL_Rect text_line_position; SDL_Rect text_line_dimension; TTF_Font * font = TTF_OpenFont(w->font_path, w->font_size); int x, y, new_line_length; TTF_SizeText(font, text, &x, &y); new_line_length = x - line_number * (w->dimensions_background.w - 2 * 2 * w->buttons_header_offset); text_line_position.x = 0; text_line_position.y = (Sint16)((line_number - 1) * y); text_line_dimension.x = (Sint16)((line_number - 1) * (w->dimensions_background.w - 2 * 2 * w->buttons_header_offset)); text_line_dimension.y = 0; text_line_dimension.w = (new_line_length > 0) ? (Uint16)(w->dimensions_background.w - 2 * 2 * w->buttons_header_offset) : (Uint16)(x / line_number); text_line_dimension.h = (Uint16)(y); TTF_FontLineSkip(font); text_line = TTF_RenderText_Blended(font, text, GUI_GetColorFromHex(w->content_text_color)); assert(w->text_content != NULL); SDL_BlitSurface(text_line, &text_line_dimension, w->text_content, &text_line_position); if (new_line_length > 0) GUI_SetTextRecursive(w, text, line_number + 1); SDL_FreeSurface(text_line); TTF_CloseFont(font); }
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); }
// // 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); }
MessageArea::MessageArea ( SDL_Surface* dest_surface, int sizex, int sizey, int originx, int originy ) : Widget( dest_surface, sizex, sizey, originx, originy ) { dest.x = originx; dest.y = originy; dest.w = sizex; dest.h = sizey; font = TTF_OpenFont ( "client/data/Vera.ttf", 12 ); if ( !font ) { std::cerr << "Error creating TTF_Font: " << TTF_GetError() << "\n"; exit ( 1 ); } font_height = TTF_FontLineSkip ( font ); message_color.r = 255; message_color.g = 255; message_color.b = 0; message_color.unused = 0; input_received = true; blocked = 0; current_message = -1; }
/*** FunciĆ³n: Pixeles recomendados para una linea nueva ***/ int GetFontLineSkip( TTF_Font* font ) { return TTF_FontLineSkip( font ); }
osd_font sdl_osd_interface::font_open(const char *_name, int &height) { TTF_Font *font = (TTF_Font *)NULL; bool bakedstyles = false; int style = 0; // accept qualifiers from the name astring name(_name); if (name == "default") { name = "Liberation Sans"; } bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0); bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0); bool underline = (name.replace(0, "[U]", "") + name.replace(0, "[u]", "") > 0); bool strike = (name.replace(0, "[S]", "") + name.replace(0, "[s]", "") > 0); // first up, try it as a filename font = TTF_OpenFont_Magic(name, POINT_SIZE); // if no success, try the font path if (!font) { mame_printf_verbose("Searching font %s in -%s\n", name.cstr(), OPTION_FONTPATH); emu_file file(machine().options().font_path(), OPEN_FLAG_READ); if (file.open(name) == FILERR_NONE) { astring full_name = file.fullpath(); font = TTF_OpenFont_Magic(full_name, POINT_SIZE); if (font) mame_printf_verbose("Found font %s\n", full_name.cstr()); } } // if that didn't work, crank up the FontConfig database #ifndef SDLMAME_HAIKU if (!font) { font = search_font_config(name, bold, italic, underline, bakedstyles); } #endif if (!font) { if (!BDF_Check_Magic(name)) { printf("WARNING: font %s, is not TrueType or BDF, using MAME default\n", name.cstr()); } return NULL; } // apply styles if (!bakedstyles) { style |= bold ? TTF_STYLE_BOLD : 0; style |= italic ? TTF_STYLE_ITALIC : 0; } style |= underline ? TTF_STYLE_UNDERLINE : 0; // SDL_ttf 2.0.9 and earlier does not define TTF_STYLE_STRIKETHROUGH #if SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) > SDL_VERSIONNUM(2,0,9) style |= strike ? TTF_STYLE_STRIKETHROUGH : 0; #else if (strike) mame_printf_warning("Ignoring strikethrough for SDL_TTF with version less 2.0.10\n"); #endif // PATCHLEVEL TTF_SetFontStyle(font, style); height = TTF_FontLineSkip(font); return (osd_font)font; }
/** * Process the text and generate the list of formatted renderables. */ void FmtTextDecor::Reformat() { int lineHeight = TTF_FontLineSkip(**font); int spaceWidth = font->spaceLayoutWidth; if (text) s = **text; int x = 0, y = 0; int fmtColor = 7; sizeWidth = 0; sizeHeight = 0; rends.clear(); rends.reserve(s.length()); uint32_t ch = 0; for (auto iter = s.cbegin(), iend = s.cend(); iter != iend; ) { ch = utf8::next(iter, iend); // Only handle characters which we have included in the type case. if (ch > font->glyphs.size()) { SDL_Log("Unrenderable code point: %d", ch); continue; } switch (ch) { case '\n': // Newlines. x = 0; y += lineHeight; break; case '^': // Color codes. if (iter == iend) { return; } else { uint32_t idx = utf8::next(iter, iend); // Allow "^^" as an escape sequence for "^". if (idx == '^') { const Ttf::Glyph &glyph = font->glyphs['^']; if (glyph.avail) { rends.emplace_back(Rend(&glyph, x, y, fmtColor)); x += glyph.layoutW; } break; } fmtColor = (idx + 16) & 31; } break; case '\r': // Ignore CRs. break; case ' ': x += spaceWidth; break; default: { const Ttf::Glyph &glyph = font->glyphs[ch]; if (!glyph.avail) continue; rends.emplace_back(Rend(&glyph, x, y, fmtColor)); x += glyph.layoutW; } } if (x >= sizeWidth) { sizeWidth = x; } } // If the last char wasn't a newline, adjust the height otherwise we'll // cut off the bottom line of text. if (ch != '\n') { y += lineHeight; } sizeHeight = y; }
/* * 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; }
//prep page void Book::drawPage(Screen &screen, int pageNum) { //clean screen screen.cleanScreen(); //init vars int textureWidth, textureHeight, txtSize, imgSizeX, imgSizeY, destX, destY, textFontSize, warningFontSize, textWidth, textFontGap, endTextSize, endMarkerX, endMarkerY; SDL_Rect destRect; //set vars textFontSize = int(screen.resY / 35); warningFontSize = int(screen.resY / 12); textWidth = screen.resX * this->pages[pageNum].textScaleX; //sample font vertical size of choice and page end text textFontGap = int(TTF_FontLineSkip(TTF_OpenFont("fonts/benguiat_bold.ttf", textFontSize)) * .79); //draw warning (if warning exists) if (this->pages[pageNum].itemType == "WARNING") { //draw text to texture screen.makeTextTexture("fonts/souvenir.ttf", warningFontSize, this->pages[pageNum].item, { 0,0,0 }, (screen.resX / 2)); //get dimensions SDL_QueryTexture(screen.texture, NULL, NULL, &textureWidth, &textureHeight); //calc text destination destX = (screen.resX * this->pages[pageNum].itemX) - (textureWidth / 2); destY = (screen.resY * this->pages[pageNum].itemY) - (textureHeight / 2); //set destination destRect = { destX, destY, textureWidth, textureHeight }; //draw texture to buffer screen.drawTexture(screen.texture, destRect); } //draw image (if image exists) if (this->pages[pageNum].itemType == "IMAGE") { //draw image to texture screen.makeImageTexture(this->pages[pageNum].item); //get dimensions SDL_QueryTexture(screen.texture, NULL, NULL, &textureWidth, &textureHeight); //calc scaled image dimensions and destination imgSizeY = int(screen.resY * this->pages[pageNum].itemScaleY); imgSizeX = int(textureWidth * (double(imgSizeY) / double(textureHeight))); destX = (screen.resX * this->pages[pageNum].itemX) - (imgSizeX / 2); destY = (screen.resY * this->pages[pageNum].itemY) - (imgSizeY / 2); //set destination destRect = { destX, destY, imgSizeX, imgSizeY }; //draw texture to buffer screen.drawTexture(screen.texture, destRect); } //draw page text //determine how many lines are needed below the text block if (this->pages[pageNum].type == "CHOICE") { //adjust size based on number of choices endTextSize = this->pages[pageNum].choices.size() * (textFontGap * 2); } else { //only one thing will be written, so just need one set endTextSize = (textFontGap * 2); } //draw text to texture screen.makeTextTexture("fonts/souvenir.ttf", textFontSize, this->pages[pageNum].text, { 50,50,50 }, textWidth); //get dimensions SDL_QueryTexture(screen.texture, NULL, NULL, &textureWidth, &textureHeight); //calc text destination destX = (screen.resX * this->pages[pageNum].textX) - (textureWidth / 2); destY = (screen.resY * this->pages[pageNum].textY) - ((textureHeight + endTextSize) / 2); //set destination destRect = { destX, destY, textureWidth, textureHeight }; //prepare end markers endMarkerX = destX; endMarkerY = destY + textureHeight + textFontGap; //draw texture to buffer screen.drawTexture(screen.texture, destRect); //draw text at the end of the page depending on page type if (this->pages[pageNum].type == "CHOICE") { //write choices //loop through choice array and write all choices to the buffer for (size_t i = 0; i < this->pages[pageNum].choices.size(); i++) { //draw text to texture screen.makeTextTexture("fonts/souvenir.ttf", textFontSize, this->pages[pageNum].choices[i].text, { 50,50,50 }, textWidth); //get dimensions SDL_QueryTexture(screen.texture, NULL, NULL, &textureWidth, &textureHeight); //set destination destRect = { endMarkerX, endMarkerY, textureWidth, textureHeight }; //draw texture to buffer screen.drawTexture(screen.texture, destRect); //increment choiceMarkerY endMarkerY = (endMarkerY + (textFontGap * 2)); } } else { //write text from the page format map //draw text to texture screen.makeTextTexture("fonts/souvenir.ttf", textFontSize, this->pageFormat[this->pages[pageNum].type].text, { 50,50,50 }, textWidth); //get dimensions SDL_QueryTexture(screen.texture, NULL, NULL, &textureWidth, &textureHeight); //set destination destRect = { endMarkerX, endMarkerY, textureWidth, textureHeight }; //draw texture to buffer screen.drawTexture(screen.texture, destRect); } //render buffer to screen screen.renderBuffer(); }
SDLFontEngine::SDLFontEngine() : FontEngine(), active_font(NULL) { // Initiate SDL_ttf if(!TTF_WasInit() && TTF_Init()==-1) { logError("SDLFontEngine: TTF_Init: %s", TTF_GetError()); Exit(2); } // load the fonts // @CLASS SDLFontEngine: Font settings|Description of engine/font_settings.txt FileParser infile; if (infile.open("engine/font_settings.txt")) { while (infile.next()) { if (infile.new_section && infile.section == "font") { SDLFontStyle f; f.name = infile.section; font_styles.push_back(SDLFontStyle()); } if (font_styles.empty()) continue; SDLFontStyle *style = &(font_styles.back()); if (infile.key == "id") { // @ATTR font.id|string|An identifier used to reference this font. style->name = infile.val; } else if (infile.key == "style") { // @ATTR font.style|repeatable(["default", predefined_string], filename, int, bool) : Language, Font file, Point size, Blending|Filename, point size, and blend mode of the font to use for this language. Language can be "default" or a 2-letter region code. std::string lang = popFirstString(infile.val); if ((lang == "default" && style->path == "") || lang == LANGUAGE) { style->path = popFirstString(infile.val); style->ptsize = popFirstInt(infile.val); style->blend = toBool(popFirstString(infile.val)); style->ttfont = TTF_OpenFont(mods->locate("fonts/" + style->path).c_str(), style->ptsize); if(style->ttfont == NULL) { logError("FontEngine: TTF_OpenFont: %s", TTF_GetError()); } else { int lineskip = TTF_FontLineSkip(style->ttfont); style->line_height = lineskip; style->font_height = lineskip; } } } } infile.close(); } // set the font colors Color color; if (infile.open("engine/font_colors.txt")) { while (infile.next()) { // @ATTR menu_normal|color|Basic menu text color. Recommended: white. // @ATTR menu_bonus|color|Positive menu text color. Recommended: green. // @ATTR menu_penalty|color|Negative menu text color. Recommended: red. // @ATTR widget_normal|color|Basic widget text color. Recommended: white. // @ATTR widget_disabled|color|Disabled widget text color. Recommended: grey. // @ATTR combat_givedmg|color|Enemy damage text color. Recommended: white. // @ATTR combat_takedmg|color|Player damage text color. Recommended: red. // @ATTR combat_crit|color|Enemy critical damage text color. Recommended: yellow. // @ATTR requirements_no_met|color|Unmet requirements text color. Recommended: red. // @ATTR item_bonus|color|Item bonus text color. Recommended: green. // @ATTR item_penalty|color|Item penalty text color. Recommended: red. // @ATTR item_flavor|color|Item flavor text color. Recommended: grey. color_map[infile.key] = toRGB(infile.val); } infile.close(); } // Attempt to set the default active font setFont("font_regular"); if (!active_font) { logError("FontEngine: Unable to determine default font!"); Exit(1); } }
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; }