/* * SCR_DrawStringWidth * * ClampS to width in pixels. Returns drawn len */ size_t SCR_DrawStringWidth( int x, int y, int align, const char *str, size_t maxwidth, qfontface_t *font, vec4_t color ) { size_t width; int fontHeight; if( !str ) return 0; if( !font ) font = cls.fontSystemSmall; fontHeight = FTLIB_FontHeight( font ); if( maxwidth < 0 ) maxwidth = 0; width = FTLIB_StringWidth( str, font, 0 ); if( width ) { if( maxwidth && width > maxwidth ) width = maxwidth; x = SCR_HorizontalAlignForString( x, align, width ); y = SCR_VerticalAlignForString( y, align, fontHeight ); return FTLIB_DrawRawString( x, y, str, maxwidth, font, color ); } return 0; }
/* * SCR_DrawString */ void SCR_DrawString( int x, int y, int align, const char *str, qfontface_t *font, vec4_t color ) { size_t width; int fontHeight; if( !str ) return; if( !font ) font = cls.fontSystemSmall; fontHeight = FTLIB_FontHeight( font ); width = FTLIB_StringWidth( str, font, 0 ); if( width ) { x = SCR_HorizontalAlignForString( x, align, width ); y = SCR_VerticalAlignForString( y, align, fontHeight ); if( y <= -fontHeight || y >= (int)viddef.height ) return; // totally off screen if( x + width <= 0 || x >= (int)viddef.width ) return; // totally off screen FTLIB_DrawRawString( x, y, str, 0, font, color ); } }
/* * SCR_DrawString */ int SCR_DrawString( int x, int y, int align, const char *str, qfontface_t *font, vec4_t color, int flags ) { int width; int fontHeight; if( !str ) return 0; if( !font ) font = cls.consoleFont; fontHeight = FTLIB_FontHeight( font ); if( ( align % 3 ) != 0 ) // not left - don't precalculate the width if not needed x = SCR_HorizontalAlignForString( x, align, FTLIB_StringWidth( str, font, 0, flags ) ); y = SCR_VerticalAlignForString( y, align, fontHeight ); FTLIB_DrawRawString( x, y, str, 0, &width, font, color, flags ); return width; }
/* FTLIB_DrawMultilineString * * Draws a string with word wrap. */ int FTLIB_DrawMultilineString( int x, int y, const char *str, int halign, int maxwidth, int maxlines, qfontface_t *font, vec4_t color, int flags ) { bool ended = false; // whether to stop drawing lines // characters and glyphs const char *oldstr; int gc, colorindex; wchar_t num, prev_num; qglyph_t *glyph, *prev_glyph; int glyph_width; renderString_f renderString; getKerning_f getKerning; bool hasKerning; // words const char *word; // beginning of the current word int word_chars, space_chars; // length of the current word and number of spaces before it int word_width, space_width; // width of the current word and the spaces before it vec4_t word_color; // starting color of the current word bool in_space; // whether currently in a sequence of spaces // line drawing const char *line; // beginning of the line int line_chars; // number of characters to draw in this line int line_width; // width of the current line int line_x; // x position of the current character in line vec4_t line_color, line_next_color; // first color in the line int line_height; // height of a single line int lines = 0; // number of lines drawn - the return value if( !str || !font || ( maxwidth <= 0 ) ) return 0; halign = halign % 3; // ignore vertical alignment renderString = font->f->renderString; getKerning = font->f->getKerning; hasKerning = ( flags & TEXTDRAWFLAG_KERNING ) && font->hasKerning; VectorCopy( color, line_next_color ); line_color[3] = color[3]; line_height = FTLIB_FontHeight( font ); do { // reset word_chars = space_chars = 0; word_width = space_width = 0; in_space = true; // assume starting from a whitespace so preceding whitespaces can be skipped line_chars = 0; line_width = 0; VectorCopy( line_next_color, line_color ); // find where to wrap prev_num = 0; prev_glyph = NULL; while( str ) { oldstr = str; gc = FTLIB_GrabChar( &str, &num, &colorindex, flags ); if( gc == GRABCHAR_CHAR ) { if( num == '\n' ) { if( !word_chars ) space_chars = space_width = 0; VectorCopy( color, line_next_color ); break; } if( num < ' ' ) continue; glyph = FTLIB_GetGlyph( font, num ); if( !glyph ) { num = FTLIB_REPLACEMENT_GLYPH; glyph = FTLIB_GetGlyph( font, num ); } if( !glyph->shader ) renderString( font, oldstr ); if( Q_IsBreakingSpaceChar( num ) ) { if( in_space ) { if( !line_chars ) continue; // skip preceding whitespaces in a line } else { in_space = true; // reached the space without wrapping - send the current word to the line line_chars += space_chars + word_chars; word_chars = space_chars = 0; line_width += space_width + word_width; word_width = space_width = 0; } space_chars++; if( hasKerning && prev_num ) space_width += getKerning( font, prev_glyph, glyph ); space_width += glyph->x_advance; } else { in_space = false; glyph_width = glyph->x_advance; if( hasKerning && prev_num ) glyph_width += getKerning( font, prev_glyph, glyph ); if( !word_chars ) { word = oldstr; VectorCopy( line_next_color, word_color ); } if( line_chars ) { // wrap after the previous word, ignoring spaces between the words if( ( line_width + space_width + word_width + glyph_width ) > maxwidth ) { str = word; VectorCopy( word_color, line_next_color ); word_chars = space_chars = 0; word_width = space_width = 0; break; } } else { line = word; if( word_chars ) // always draw at least 1 character in a line { if( ( word_width + glyph_width ) > maxwidth ) { str = oldstr; break; } } } word_chars++; word_width += glyph_width; } prev_num = num; prev_glyph = glyph; } else if( gc == GRABCHAR_COLOR ) { assert( ( unsigned )colorindex < MAX_S_COLORS ); VectorCopy( color_table[colorindex], line_next_color ); if( !line_chars && !word_chars ) VectorCopy( line_next_color, line_color ); } else if( gc == GRABCHAR_END ) { ended = true; break; } else assert( 0 ); } // add the remaining part of the word line_chars += space_chars + word_chars; line_width += space_width + word_width; // draw the line if( line_chars > 0 ) { line_x = x; if( halign == ALIGN_CENTER_TOP ) line_x -= line_width >> 1; else if( halign == ALIGN_RIGHT_TOP ) line_x -= line_width; prev_num = 0; prev_glyph = NULL; while( ( line_chars > 0 ) && line ) { gc = FTLIB_GrabChar( &line, &num, &colorindex, flags ); if( gc == GRABCHAR_CHAR ) { if( num < ' ' ) continue; line_chars--; glyph = FTLIB_GetGlyph( font, num ); if( !glyph ) { num = FTLIB_REPLACEMENT_GLYPH; glyph = FTLIB_GetGlyph( font, num ); } if( hasKerning && prev_num ) line_x += getKerning( font, prev_glyph, glyph ); FTLIB_DrawRawChar( line_x, y, num, font, line_color ); line_x += glyph->x_advance; prev_num = num; prev_glyph = glyph; } else if( gc == GRABCHAR_COLOR ) { assert( ( unsigned )colorindex < MAX_S_COLORS ); VectorCopy( color_table[colorindex], line_color ); } else if( gc == GRABCHAR_END ) break; else assert( 0 ); } }
size_t SCR_strHeight( qfontface_t *font ) { return FTLIB_FontHeight( font ); }