From 409e3f0cd3bf9a0ce62779390634c6de674633d9 Mon Sep 17 00:00:00 2001 From: pelya Date: Thu, 31 May 2012 14:58:53 +0300 Subject: [PATCH] Updated SDL_ttf --- project/jni/sdl_ttf/SDL_ttf.c | 759 ++++++++++++++++++-------- project/jni/sdl_ttf/glfont.c | 98 ++-- project/jni/sdl_ttf/include/SDL_ttf.h | 61 ++- project/jni/sdl_ttf/showfont.c | 182 +++--- 4 files changed, 698 insertions(+), 402 deletions(-) diff --git a/project/jni/sdl_ttf/SDL_ttf.c b/project/jni/sdl_ttf/SDL_ttf.c index 6ed397400..64bcfa509 100644 --- a/project/jni/sdl_ttf/SDL_ttf.c +++ b/project/jni/sdl_ttf/SDL_ttf.c @@ -1,27 +1,24 @@ /* - SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts - Copyright (C) 1997-2004 Sam Lantinga + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 2001-2012 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. */ -/* $Id: SDL_ttf.c 3284 2007-07-15 06:18:29Z slouken $ */ - #include #include #include @@ -42,6 +39,8 @@ #include #include FT_FREETYPE_H #include FT_OUTLINE_H +#include FT_STROKER_H +#include FT_GLYPH_H #include FT_TRUETYPE_IDS_H #include "SDL.h" @@ -88,7 +87,12 @@ struct _TTF_Font { int lineskip; /* The font style */ + int face_style; int style; + int outline; + + /* Whether kerning is desired */ + int kerning; /* Extra width in glyph bounds for text styles */ int glyph_overhang; @@ -100,8 +104,7 @@ struct _TTF_Font { /* Cache for style-transformed glyphs */ c_glyph *current; - c_glyph cache[256]; - c_glyph scratch; + c_glyph cache[257]; /* 257 is a prime */ /* We are responsible for closing the font stream */ SDL_RWops *src; @@ -110,38 +113,175 @@ struct _TTF_Font { /* For non-scalable formats, we must remember which font index size */ int font_size_family; + + /* really just flags passed into FT_Load_Glyph */ + int hinting; }; +/* Handle a style only if the font does not already handle it */ +#define TTF_HANDLE_STYLE_BOLD(font) (((font)->style & TTF_STYLE_BOLD) && \ + !((font)->face_style & TTF_STYLE_BOLD)) +#define TTF_HANDLE_STYLE_ITALIC(font) (((font)->style & TTF_STYLE_ITALIC) && \ + !((font)->face_style & TTF_STYLE_ITALIC)) +#define TTF_HANDLE_STYLE_UNDERLINE(font) ((font)->style & TTF_STYLE_UNDERLINE) +#define TTF_HANDLE_STYLE_STRIKETHROUGH(font) ((font)->style & TTF_STYLE_STRIKETHROUGH) + +/* Font styles that does not impact glyph drawing */ +#define TTF_STYLE_NO_GLYPH_CHANGE (TTF_STYLE_UNDERLINE | TTF_STYLE_STRIKETHROUGH) + /* The FreeType font engine/library */ static FT_Library library; static int TTF_initialized = 0; static int TTF_byteswapped = 0; -/* UNICODE string utilities */ -static __inline__ int UNICODE_strlen(const Uint16 *text) + +/* Gets the top row of the underline. The outline + is taken into account. +*/ +static __inline__ int TTF_underline_top_row(TTF_Font *font) { - int size = 0; - while ( *text++ ) { - ++size; - } - return size; + /* With outline, the underline_offset is underline_offset+outline. */ + /* So, we don't have to remove the top part of the outline height. */ + return font->ascent - font->underline_offset - 1; } -static __inline__ void UNICODE_strcpy(Uint16 *dst, const Uint16 *src, int swap) + +/* Gets the top row of the underline. for a given glyph. The outline + is taken into account. + Need to update row according to height difference between font and glyph: + font_value - font->ascent + glyph->maxy +*/ +static __inline__ int TTF_Glyph_underline_top_row(TTF_Font *font, c_glyph *glyph) { - if ( swap ) { - while ( *src ) { - *dst = SDL_Swap16(*src); - ++src; - ++dst; + return glyph->maxy - font->underline_offset - 1; +} + +/* Gets the bottom row of the underline. The outline + is taken into account. +*/ +static __inline__ int TTF_underline_bottom_row(TTF_Font *font) +{ + int row = TTF_underline_top_row(font) + font->underline_height; + if( font->outline > 0 ) { + /* Add underline_offset outline offset and */ + /* the bottom part of the outline. */ + row += font->outline * 2; + } + return row; +} + +/* Gets the bottom row of the underline. for a given glyph. The outline + is taken into account. + Need to update row according to height difference between font and glyph: + font_value - font->ascent + glyph->maxy +*/ +static __inline__ int TTF_Glyph_underline_bottom_row(TTF_Font *font, c_glyph *glyph) +{ + return TTF_underline_bottom_row(font) - font->ascent + glyph->maxy; +} + +/* Gets the top row of the strikethrough. The outline + is taken into account. +*/ +static __inline__ int TTF_strikethrough_top_row(TTF_Font *font) +{ + /* With outline, the first text row is 'outline'. */ + /* So, we don't have to remove the top part of the outline height. */ + return font->height / 2; +} + +/* Gets the top row of the strikethrough for a given glyph. The outline + is taken into account. + Need to update row according to height difference between font and glyph: + font_value - font->ascent + glyph->maxy +*/ +static __inline__ int TTF_Glyph_strikethrough_top_row(TTF_Font *font, c_glyph *glyph) +{ + return TTF_strikethrough_top_row(font) - font->ascent + glyph->maxy; +} + +static void TTF_initLineMectrics(const TTF_Font *font, const SDL_Surface *textbuf, const int row, Uint8 **pdst, int *pheight) +{ + Uint8 *dst; + int height; + + dst = (Uint8 *)textbuf->pixels; + if( row > 0 ) { + dst += row * textbuf->pitch; + } + + height = font->underline_height; + /* Take outline into account */ + if( font->outline > 0 ) { + height += font->outline * 2; + } + *pdst = dst; + *pheight = height; +} + +/* Draw a solid line of underline_height (+ optional outline) + at the given row. The row value must take the + outline into account. +*/ +static void TTF_drawLine_Solid(const TTF_Font *font, const SDL_Surface *textbuf, const int row) +{ + int line; + Uint8 *dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h; + Uint8 *dst; + int height; + + TTF_initLineMectrics(font, textbuf, row, &dst, &height); + + /* Draw line */ + for ( line=height; line>0 && dst < dst_check; --line ) { + /* 1 because 0 is the bg color */ + memset( dst, 1, textbuf->w ); + dst += textbuf->pitch; + } +} + +/* Draw a shaded line of underline_height (+ optional outline) + at the given row. The row value must take the + outline into account. +*/ +static void TTF_drawLine_Shaded(const TTF_Font *font, const SDL_Surface *textbuf, const int row) +{ + int line; + Uint8 *dst_check = (Uint8*)textbuf->pixels + textbuf->pitch * textbuf->h; + Uint8 *dst; + int height; + + TTF_initLineMectrics(font, textbuf, row, &dst, &height); + + /* Draw line */ + for ( line=height; line>0 && dst < dst_check; --line ) { + memset( dst, NUM_GRAYS - 1, textbuf->w ); + dst += textbuf->pitch; + } +} + +/* Draw a blended line of underline_height (+ optional outline) + at the given row. The row value must take the + outline into account. +*/ +static void TTF_drawLine_Blended(const TTF_Font *font, const SDL_Surface *textbuf, const int row, const Uint32 color) +{ + int line; + Uint32 *dst_check = (Uint32*)textbuf->pixels + textbuf->pitch/4 * textbuf->h; + Uint8 *dst8; /* destination, byte version */ + Uint32 *dst; + int height; + int col; + Uint32 pixel = color | 0xFF000000; /* Amask */ + + TTF_initLineMectrics(font, textbuf, row, &dst8, &height); + dst = (Uint32 *) dst8; + + /* Draw line */ + for ( line=height; line>0 && dst < dst_check; --line ) { + for ( col=0; col < textbuf->w; ++col ) { + dst[col] = pixel; } - *dst = '\0'; - } else { - while ( *src ) { - *dst = *src; - ++src; - ++dst; - } - *dst = '\0'; + dst += textbuf->pitch/4; } } @@ -222,7 +362,7 @@ static unsigned long RWread( SDL_RWops *src; src = (SDL_RWops *)stream->descriptor.pointer; - SDL_RWseek( src, (int)offset, SEEK_SET ); + SDL_RWseek( src, (int)offset, RW_SEEK_SET ); if ( count == 0 ) { return 0; } @@ -236,7 +376,8 @@ TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long ind FT_Face face; FT_Fixed scale; FT_Stream stream; - int position; + FT_CharMap found; + int position, i; if ( ! TTF_initialized ) { TTF_SetError( "Library not initialized" ); @@ -271,9 +412,9 @@ TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long ind stream->read = RWread; stream->descriptor.pointer = src; stream->pos = (unsigned long)position; - SDL_RWseek(src, 0, SEEK_END); + SDL_RWseek(src, 0, RW_SEEK_END); stream->size = (unsigned long)(SDL_RWtell(src) - position); - SDL_RWseek(src, position, SEEK_SET); + SDL_RWseek(src, position, RW_SEEK_SET); font->args.flags = FT_OPEN_STREAM; font->args.stream = stream; @@ -286,6 +427,23 @@ TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long ind } face = font->face; + /* Set charmap for loaded font */ + found = 0; + for (i = 0; i < face->num_charmaps; i++) { + FT_CharMap charmap = face->charmaps[i]; + if ((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Unicode */ + || (charmap->platform_id == 3 && charmap->encoding_id == 0) /* Windows Symbol */ + || (charmap->platform_id == 2 && charmap->encoding_id == 1) /* ISO Unicode */ + || (charmap->platform_id == 0)) { /* Apple Unicode */ + found = charmap; + break; + } + } + if ( found ) { + /* If this fails, continue using the default charmap */ + FT_Set_Charmap(face, found); + } + /* Make sure that our font face is scalable (global metrics) */ if ( FT_IS_SCALABLE(face) ) { @@ -342,10 +500,22 @@ TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long ind font->height, font->lineskip); printf("\tunderline_offset = %d, underline_height = %d\n", font->underline_offset, font->underline_height); + printf("\tunderline_top_row = %d, strikethrough_top_row = %d\n", + TTF_underline_top_row(font), TTF_strikethrough_top_row(font)); #endif + /* Initialize the font face style */ + font->face_style = TTF_STYLE_NORMAL; + if ( font->face->style_flags & FT_STYLE_FLAG_BOLD ) { + font->face_style |= TTF_STYLE_BOLD; + } + if ( font->face->style_flags & FT_STYLE_FLAG_ITALIC ) { + font->face_style |= TTF_STYLE_ITALIC; + } /* Set the default font style */ - font->style = TTF_STYLE_NORMAL; + font->style = font->face_style; + font->outline = 0; + font->kerning = 1; font->glyph_overhang = face->size->metrics.y_ppem / 10; /* x offset = cos(((90.0-12)/360)*2*M_PI), or 12 degree angle */ font->glyph_italics = 0.207f; @@ -400,10 +570,6 @@ static void Flush_Cache( TTF_Font* font ) } } - if( font->scratch.cached ) { - Flush_Glyph( &font->scratch ); - } - } static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want ) @@ -424,7 +590,7 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want if ( ! cached->index ) { cached->index = FT_Get_Char_Index( face, ch ); } - error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT ); + error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT | font->hinting); if( error ) { return error; } @@ -460,10 +626,10 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want } /* Adjust for bold and italic text */ - if( font->style & TTF_STYLE_BOLD ) { + if( TTF_HANDLE_STYLE_BOLD(font) ) { cached->maxx += font->glyph_overhang; } - if( font->style & TTF_STYLE_ITALIC ) { + if( TTF_HANDLE_STYLE_ITALIC(font) ) { cached->maxx += (int)ceil(font->glyph_italics); } cached->stored |= CACHED_METRICS; @@ -475,9 +641,10 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want int i; FT_Bitmap* src; FT_Bitmap* dst; + FT_Glyph bitmap_glyph = NULL; /* Handle the italic style */ - if( font->style & TTF_STYLE_ITALIC ) { + if( TTF_HANDLE_STYLE_ITALIC(font) ) { FT_Matrix shear; shear.xx = 1 << 16; @@ -488,18 +655,33 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want FT_Outline_Transform( outline, &shear ); } - /* Render the glyph */ - if ( mono ) { - error = FT_Render_Glyph( glyph, ft_render_mode_mono ); + /* Render as outline */ + if( (font->outline > 0) && glyph->format != FT_GLYPH_FORMAT_BITMAP ) { + FT_Stroker stroker; + FT_Get_Glyph( glyph, &bitmap_glyph ); + error = FT_Stroker_New( library, &stroker ); + if( error ) { + return error; + } + FT_Stroker_Set( stroker, font->outline * 64, FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0 ); + FT_Glyph_Stroke( &bitmap_glyph, stroker, 1 /* delete the original glyph */ ); + FT_Stroker_Done( stroker ); + /* Render the glyph */ + error = FT_Glyph_To_Bitmap( &bitmap_glyph, mono ? ft_render_mode_mono : ft_render_mode_normal, 0, 1 ); + if( error ) { + FT_Done_Glyph( bitmap_glyph ); + return error; + } + src = &((FT_BitmapGlyph)bitmap_glyph)->bitmap; } else { - error = FT_Render_Glyph( glyph, ft_render_mode_normal ); + /* Render the glyph */ + error = FT_Render_Glyph( glyph, mono ? ft_render_mode_mono : ft_render_mode_normal ); + if( error ) { + return error; + } + src = &glyph->bitmap; } - if( error ) { - return error; - } - /* Copy over information to cache */ - src = &glyph->bitmap; if ( mono ) { dst = &cached->bitmap; } else { @@ -517,21 +699,21 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want * FT_Render_Glyph() canreturn two-color bitmap or 4/16/256- * color graymap according to the format of embedded bitmap/ * graymap. */ - if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) { + if ( src->pixel_mode == FT_PIXEL_MODE_MONO ) { dst->pitch *= 8; - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY2 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY2 ) { dst->pitch *= 4; - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY4 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY4 ) { dst->pitch *= 2; } /* Adjust for bold and italic text */ - if( font->style & TTF_STYLE_BOLD ) { + if( TTF_HANDLE_STYLE_BOLD(font) ) { int bump = font->glyph_overhang; dst->pitch += bump; dst->width += bump; } - if( font->style & TTF_STYLE_ITALIC ) { + if( TTF_HANDLE_STYLE_ITALIC(font) ) { int bump = (int)ceil(font->glyph_italics); dst->pitch += bump; dst->width += bump; @@ -551,50 +733,50 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want unsigned char *srcp = src->buffer + soffset; unsigned char *dstp = dst->buffer + doffset; int j; - if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) { + if ( src->pixel_mode == FT_PIXEL_MODE_MONO ) { for ( j = 0; j < src->width; j += 8 ) { - unsigned char ch = *srcp++; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; - ch <<= 1; - *dstp++ = (ch&0x80) >> 7; + unsigned char c = *srcp++; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; + c <<= 1; + *dstp++ = (c&0x80) >> 7; } - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY2 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY2 ) { for ( j = 0; j < src->width; j += 4 ) { - unsigned char ch = *srcp++; - *dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0; - ch <<= 2; - *dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0; - ch <<= 2; - *dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0; - ch <<= 2; - *dstp++ = (((ch&0xA0) >> 6) >= 0x2) ? 1 : 0; + unsigned char c = *srcp++; + *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0; + c <<= 2; + *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0; + c <<= 2; + *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0; + c <<= 2; + *dstp++ = (((c&0xA0) >> 6) >= 0x2) ? 1 : 0; } - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY4 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY4 ) { for ( j = 0; j < src->width; j += 2 ) { - unsigned char ch = *srcp++; - *dstp++ = (((ch&0xF0) >> 4) >= 0x8) ? 1 : 0; - ch <<= 4; - *dstp++ = (((ch&0xF0) >> 4) >= 0x8) ? 1 : 0; + unsigned char c = *srcp++; + *dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0; + c <<= 4; + *dstp++ = (((c&0xF0) >> 4) >= 0x8) ? 1 : 0; } } else { for ( j = 0; j < src->width; j++ ) { - unsigned char ch = *srcp++; - *dstp++ = (ch >= 0x80) ? 1 : 0; + unsigned char c = *srcp++; + *dstp++ = (c >= 0x80) ? 1 : 0; } } - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_MONO ) { /* This special case wouldn't * be here if the FT_Render_Glyph() * function wasn't buggy when it tried @@ -606,49 +788,49 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want * */ unsigned char *srcp = src->buffer + soffset; unsigned char *dstp = dst->buffer + doffset; - unsigned char ch; + unsigned char c; int j, k; for ( j = 0; j < src->width; j += 8) { - ch = *srcp++; + c = *srcp++; for (k = 0; k < 8; ++k) { - if ((ch&0x80) >> 7) { + if ((c&0x80) >> 7) { *dstp++ = NUM_GRAYS - 1; } else { *dstp++ = 0x00; } - ch <<= 1; + c <<= 1; } } - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY2 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY2 ) { unsigned char *srcp = src->buffer + soffset; unsigned char *dstp = dst->buffer + doffset; - unsigned char ch; + unsigned char c; int j, k; for ( j = 0; j < src->width; j += 4 ) { - ch = *srcp++; + c = *srcp++; for ( k = 0; k < 4; ++k ) { - if ((ch&0xA0) >> 6) { - *dstp++ = NUM_GRAYS * ((ch&0xA0) >> 6) / 3 - 1; + if ((c&0xA0) >> 6) { + *dstp++ = NUM_GRAYS * ((c&0xA0) >> 6) / 3 - 1; } else { *dstp++ = 0x00; } - ch <<= 2; + c <<= 2; } } - } else if ( glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY4 ) { + } else if ( src->pixel_mode == FT_PIXEL_MODE_GRAY4 ) { unsigned char *srcp = src->buffer + soffset; unsigned char *dstp = dst->buffer + doffset; - unsigned char ch; + unsigned char c; int j, k; for ( j = 0; j < src->width; j += 2 ) { - ch = *srcp++; + c = *srcp++; for ( k = 0; k < 2; ++k ) { - if ((ch&0xF0) >> 4) { - *dstp++ = NUM_GRAYS * ((ch&0xF0) >> 4) / 15 - 1; + if ((c&0xF0) >> 4) { + *dstp++ = NUM_GRAYS * ((c&0xF0) >> 4) / 15 - 1; } else { *dstp++ = 0x00; } - ch <<= 4; + c <<= 4; } } } else { @@ -659,7 +841,7 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want } /* Handle the bold style */ - if ( font->style & TTF_STYLE_BOLD ) { + if ( TTF_HANDLE_STYLE_BOLD(font) ) { int row; int col; int offset; @@ -691,6 +873,11 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want } else { cached->stored |= CACHED_PIXMAP; } + + /* Free outlined glyph */ + if( bitmap_glyph ) { + FT_Done_Glyph( bitmap_glyph ); + } } /* We're done, mark this glyph cached */ @@ -702,15 +889,14 @@ static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want static FT_Error Find_Glyph( TTF_Font* font, Uint16 ch, int want ) { int retval = 0; + int hsize = sizeof( font->cache ) / sizeof( font->cache[0] ); + + int h = ch % hsize; + font->current = &font->cache[h]; + + if (font->current->cached != ch) + Flush_Glyph( font->current ); - if( ch < 256 ) { - font->current = &font->cache[ch]; - } else { - if ( font->scratch.cached != ch ) { - Flush_Glyph( &font->scratch ); - } - font->current = &font->scratch; - } if ( (font->current->stored & want) != want ) { retval = Load_Glyph( font, ch, font->current, want ); } @@ -795,6 +981,16 @@ int TTF_FontLineSkip(const TTF_Font *font) return(font->lineskip); } +int TTF_GetFontKerning(const TTF_Font *font) +{ + return(font->kerning); +} + +void TTF_SetFontKerning(TTF_Font *font, int allowed) +{ + font->kerning = allowed; +} + long TTF_FontFaces(const TTF_Font *font) { return(font->face->num_faces); @@ -815,6 +1011,11 @@ char *TTF_FontFaceStyleName(const TTF_Font *font) return(font->face->style_name); } +int TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch) +{ + return(FT_Get_Char_Index(font->face, ch)); +} + int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, int* minx, int* maxx, int* miny, int* maxy, int* advance) { @@ -831,7 +1032,7 @@ int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, } if ( maxx ) { *maxx = font->current->maxx; - if( font->style & TTF_STYLE_BOLD ) { + if( TTF_HANDLE_STYLE_BOLD(font) ) { *maxx += font->glyph_overhang; } } @@ -843,7 +1044,7 @@ int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch, } if ( advance ) { *advance = font->current->advance; - if( font->style & TTF_STYLE_BOLD ) { + if( TTF_HANDLE_STYLE_BOLD(font) ) { *advance += font->glyph_overhang; } } @@ -910,6 +1111,7 @@ int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) FT_Error error; FT_Long use_kerning; FT_UInt prev_index = 0; + int outline_delta = 0; /* Initialize everything to 0 */ if ( ! TTF_initialized ) { @@ -922,7 +1124,12 @@ int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) swapped = TTF_byteswapped; /* check kerning */ - use_kerning = FT_HAS_KERNING( font->face ); + use_kerning = FT_HAS_KERNING( font->face ) && font->kerning; + + /* Init outline handling */ + if ( font->outline > 0 ) { + outline_delta = font->outline * 2; + } /* Load each character and sum it's bounding box */ x= 0; @@ -948,6 +1155,7 @@ int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) error = Find_Glyph(font, c, CACHED_METRICS); if ( error ) { + TTF_SetFTError("Couldn't find glyph", error); return -1; } glyph = font->current; @@ -983,7 +1191,7 @@ int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) if ( minx > z ) { minx = z; } - if ( font->style & TTF_STYLE_BOLD ) { + if ( TTF_HANDLE_STYLE_BOLD(font) ) { x += font->glyph_overhang; } if ( glyph->advance > glyph->maxx ) { @@ -1007,14 +1215,23 @@ int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h) /* Fill the bounds rectangle */ if ( w ) { - *w = (maxx - minx); + /* Add outline extra width */ + *w = (maxx - minx) + outline_delta; } if ( h ) { -#if 0 /* This is correct, but breaks many applications */ - *h = (maxy - miny); -#else - *h = font->height; -#endif + /* Some fonts descend below font height (FletcherGothicFLF) */ + /* Add outline extra height */ + *h = (font->ascent - miny) + outline_delta; + if ( *h < font->height ) { + *h = font->height; + } + /* Update height according to the needs of the underline style */ + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + int bottom_row = TTF_underline_bottom_row(font); + if ( *h < bottom_row ) { + *h = bottom_row; + } + } } return status; } @@ -1063,7 +1280,7 @@ SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font, return(NULL); } *unicode_text = UNICODE_BOM_NATIVE; - UTF8_to_UNICODE(unicode_text, text, unicode_len); + UTF8_to_UNICODE(unicode_text+1, text, unicode_len); /* Render the new text */ textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg); @@ -1095,14 +1312,13 @@ SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, FT_UInt prev_index = 0; /* Get the dimensions of the text surface */ - if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 0 ) || !width ) { + if( ( TTF_SizeUNICODE(font, text, &width, &height) < 0 ) || !width ) { TTF_SetError( "Text has zero width" ); return NULL; } - height = font->height; /* Create the target surface */ - textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); + textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); if( textbuf == NULL ) { return NULL; } @@ -1119,10 +1335,10 @@ SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, palette->colors[1].r = fg.r; palette->colors[1].g = fg.g; palette->colors[1].b = fg.b; - SDL_SetColorKey( textbuf, SDL_SRCCOLORKEY, 0 ); + SDL_SetColorKey( textbuf, SDL_TRUE, 0 ); /* check kerning */ - use_kerning = FT_HAS_KERNING( font->face ); + use_kerning = FT_HAS_KERNING( font->face ) && font->kerning; /* Load and render each character */ xstart = 0; @@ -1149,6 +1365,7 @@ SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, error = Find_Glyph(font, c, CACHED_METRICS|CACHED_BITMAP); if( error ) { + TTF_SetFTError("Couldn't find glyph", error); SDL_FreeSurface( textbuf ); return NULL; } @@ -1157,7 +1374,7 @@ SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, /* Ensure the width of the pixmap is correct. On some cases, * freetype may report a larger pixmap than possible.*/ width = current->width; - if (width > glyph->maxx - glyph->minx) { + if (font->outline <= 0 && width > glyph->maxx - glyph->minx) { width = glyph->maxx - glyph->minx; } /* do kerning, if possible AC-Patch */ @@ -1191,24 +1408,22 @@ SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font, } xstart += glyph->advance; - if ( font->style & TTF_STYLE_BOLD ) { + if ( TTF_HANDLE_STYLE_BOLD(font) ) { xstart += font->glyph_overhang; } prev_index = glyph->index; } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch; - for ( row=font->underline_height; row>0; --row ) { - /* 1 because 0 is the bg color */ - memset( dst, 1, textbuf->w ); - dst += textbuf->pitch; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_underline_top_row(font); + TTF_drawLine_Solid(font, textbuf, row); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_strikethrough_top_row(font); + TTF_drawLine_Solid(font, textbuf, row); } return textbuf; } @@ -1225,14 +1440,24 @@ SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg) /* Get the glyph itself */ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_BITMAP); if ( error ) { + TTF_SetFTError("Couldn't find glyph", error); return(NULL); } glyph = font->current; /* Create the target surface */ + row = glyph->bitmap.rows; + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + /* Update height according to the needs of the underline style */ + int bottom_row = TTF_Glyph_underline_bottom_row(font, glyph); + if ( row < bottom_row ) { + row = bottom_row; + } + } + textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE, - glyph->bitmap.pitch, - glyph->bitmap.rows, + glyph->bitmap.width, + row, 8, 0, 0, 0, 0 ); if ( ! textbuf ) { return(NULL); @@ -1246,29 +1471,27 @@ SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg) palette->colors[1].r = fg.r; palette->colors[1].g = fg.g; palette->colors[1].b = fg.b; - SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 0); + SDL_SetColorKey(textbuf, SDL_TRUE, 0); /* Copy the character from the pixmap */ src = glyph->bitmap.buffer; dst = (Uint8*) textbuf->pixels; - for ( row = 0; row < textbuf->h; ++row ) { - memcpy( dst, src, glyph->bitmap.pitch ); + for ( row = 0; row < glyph->bitmap.rows; ++row ) { + memcpy( dst, src, glyph->bitmap.width ); src += glyph->bitmap.pitch; dst += textbuf->pitch; } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch; - for ( row=font->underline_height; row>0; --row ) { - /* 1 because 0 is the bg color */ - memset( dst, 1, textbuf->w ); - dst += textbuf->pitch; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_Glyph_underline_top_row(font, glyph); + TTF_drawLine_Solid(font, textbuf, row); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_Glyph_strikethrough_top_row(font, glyph); + TTF_drawLine_Solid(font, textbuf, row); } return(textbuf); } @@ -1355,14 +1578,13 @@ SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font, FT_UInt prev_index = 0; /* Get the dimensions of the text surface */ - if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 0 ) || !width ) { + if( ( TTF_SizeUNICODE(font, text, &width, &height) < 0 ) || !width ) { TTF_SetError("Text has zero width"); return NULL; } - height = font->height; /* Create the target surface */ - textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); + textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0); if( textbuf == NULL ) { return NULL; } @@ -1384,7 +1606,7 @@ SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font, } /* check kerning */ - use_kerning = FT_HAS_KERNING( font->face ); + use_kerning = FT_HAS_KERNING( font->face ) && font->kerning; /* Load and render each character */ xstart = 0; @@ -1411,6 +1633,7 @@ SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font, error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP); if( error ) { + TTF_SetFTError("Couldn't find glyph", error); SDL_FreeSurface( textbuf ); return NULL; } @@ -1418,7 +1641,7 @@ SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font, /* Ensure the width of the pixmap is correct. On some cases, * freetype may report a larger pixmap than possible.*/ width = glyph->pixmap.width; - if (width > glyph->maxx - glyph->minx) { + if (font->outline <= 0 && width > glyph->maxx - glyph->minx) { width = glyph->maxx - glyph->minx; } /* do kerning, if possible AC-Patch */ @@ -1452,23 +1675,22 @@ SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font, } xstart += glyph->advance; - if( font->style & TTF_STYLE_BOLD ) { + if( TTF_HANDLE_STYLE_BOLD(font) ) { xstart += font->glyph_overhang; } prev_index = glyph->index; } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch; - for ( row=font->underline_height; row>0; --row ) { - memset( dst, NUM_GRAYS - 1, textbuf->w ); - dst += textbuf->pitch; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_underline_top_row(font); + TTF_drawLine_Shaded(font, textbuf, row); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_strikethrough_top_row(font); + TTF_drawLine_Shaded(font, textbuf, row); } return textbuf; } @@ -1493,14 +1715,24 @@ SDL_Surface* TTF_RenderGlyph_Shaded( TTF_Font* font, /* Get the glyph itself */ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP); if( error ) { + TTF_SetFTError("Couldn't find glyph", error); return NULL; } glyph = font->current; /* Create the target surface */ + row = glyph->pixmap.rows; + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + /* Update height according to the needs of the underline style */ + int bottom_row = TTF_Glyph_underline_bottom_row(font, glyph); + if ( row < bottom_row ) { + row = bottom_row; + } + } + textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE, glyph->pixmap.width, - glyph->pixmap.rows, + row, 8, 0, 0, 0, 0 ); if( !textbuf ) { return NULL; @@ -1520,23 +1752,22 @@ SDL_Surface* TTF_RenderGlyph_Shaded( TTF_Font* font, /* Copy the character from the pixmap */ src = glyph->pixmap.buffer; dst = (Uint8*) textbuf->pixels; - for ( row = 0; row < textbuf->h; ++row ) { - memcpy( dst, src, glyph->pixmap.pitch ); + for ( row = 0; row < glyph->bitmap.rows; ++row ) { + memcpy( dst, src, glyph->pixmap.width ); src += glyph->pixmap.pitch; dst += textbuf->pitch; } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch; - for ( row=font->underline_height; row>0; --row ) { - memset( dst, NUM_GRAYS - 1, textbuf->w ); - dst += textbuf->pitch; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_Glyph_underline_top_row(font, glyph); + TTF_drawLine_Shaded(font, textbuf, row); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_Glyph_strikethrough_top_row(font, glyph); + TTF_drawLine_Shaded(font, textbuf, row); } return textbuf; } @@ -1615,13 +1846,13 @@ SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, FT_UInt prev_index = 0; /* Get the dimensions of the text surface */ - if ( (TTF_SizeUNICODE(font, text, &width, NULL) < 0) || !width ) { + if ( (TTF_SizeUNICODE(font, text, &width, &height) < 0) || !width ) { TTF_SetError("Text has zero width"); return(NULL); } - height = font->height; - textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 32, + /* Create the target surface */ + textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); if ( textbuf == NULL ) { return(NULL); @@ -1632,7 +1863,7 @@ SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, dst_check = (Uint32*)textbuf->pixels + textbuf->pitch/4 * textbuf->h; /* check kerning */ - use_kerning = FT_HAS_KERNING( font->face ); + use_kerning = FT_HAS_KERNING( font->face ) && font->kerning; /* Load and render each character */ xstart = 0; @@ -1661,6 +1892,7 @@ SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, } error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP); if( error ) { + TTF_SetFTError("Couldn't find glyph", error); SDL_FreeSurface( textbuf ); return NULL; } @@ -1668,7 +1900,7 @@ SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, /* Ensure the width of the pixmap is correct. On some cases, * freetype may report a larger pixmap than possible.*/ width = glyph->pixmap.width; - if (width > glyph->maxx - glyph->minx) { + if (font->outline <= 0 && width > glyph->maxx - glyph->minx) { width = glyph->maxx - glyph->minx; } /* do kerning, if possible AC-Patch */ @@ -1707,26 +1939,22 @@ SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font, } xstart += glyph->advance; - if ( font->style & TTF_STYLE_BOLD ) { + if ( TTF_HANDLE_STYLE_BOLD(font) ) { xstart += font->glyph_overhang; } prev_index = glyph->index; } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4; - pixel |= 0xFF000000; /* Amask */ - for ( row=font->underline_height; row>0; --row ) { - for ( col=0; col < textbuf->w; ++col ) { - dst[col] = pixel; - } - dst += textbuf->pitch/4; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_underline_top_row(font); + TTF_drawLine_Blended(font, textbuf, row, pixel); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_strikethrough_top_row(font); + TTF_drawLine_Blended(font, textbuf, row, pixel); } return(textbuf); } @@ -1745,12 +1973,23 @@ SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg) /* Get the glyph itself */ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP); if ( error ) { + TTF_SetFTError("Couldn't find glyph", error); return(NULL); } glyph = font->current; + /* Create the target surface */ + row = glyph->pixmap.rows; + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + /* Update height according to the needs of the underline style */ + int bottom_row = TTF_Glyph_underline_bottom_row(font, glyph); + if ( row < bottom_row ) { + row = bottom_row; + } + } + textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE, - glyph->pixmap.width, glyph->pixmap.rows, 32, + glyph->pixmap.width, row, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); if ( ! textbuf ) { return(NULL); @@ -1760,7 +1999,7 @@ SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg) pixel = (fg.r<<16)|(fg.g<<8)|fg.b; SDL_FillRect(textbuf, NULL, pixel); /* Initialize with fg and 0 alpha */ - for ( row=0; rowh; ++row ) { + for ( row=0; rowpixmap.rows; ++row ) { /* Changed src to take pitch into account, not just width */ src = glyph->pixmap.buffer + row * glyph->pixmap.pitch; dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4; @@ -1771,27 +2010,30 @@ SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg) } /* Handle the underline style */ - if( font->style & TTF_STYLE_UNDERLINE ) { - row = font->ascent - font->underline_offset - 1; - if ( row >= textbuf->h) { - row = (textbuf->h-1) - font->underline_height; - } - dst = (Uint32 *)textbuf->pixels + row * textbuf->pitch/4; - pixel |= 0xFF000000; /* Amask */ - for ( row=font->underline_height; row>0; --row ) { - for ( col=0; col < textbuf->w; ++col ) { - dst[col] = pixel; - } - dst += textbuf->pitch/4; - } + if( TTF_HANDLE_STYLE_UNDERLINE(font) ) { + row = TTF_Glyph_underline_top_row(font, glyph); + TTF_drawLine_Blended(font, textbuf, row, pixel); + } + + /* Handle the strikethrough style */ + if( TTF_HANDLE_STYLE_STRIKETHROUGH(font) ) { + row = TTF_Glyph_strikethrough_top_row(font, glyph); + TTF_drawLine_Blended(font, textbuf, row, pixel); } return(textbuf); } void TTF_SetFontStyle( TTF_Font* font, int style ) { - font->style = style; - Flush_Cache( font ); + int prev_style = font->style; + font->style = style | font->face_style; + + /* Flush the cache if the style has changed. + * Ignore UNDERLINE which does not impact glyph drawning. + * */ + if ( (font->style | TTF_STYLE_NO_GLYPH_CHANGE ) != ( prev_style | TTF_STYLE_NO_GLYPH_CHANGE )) { + Flush_Cache( font ); + } } int TTF_GetFontStyle( const TTF_Font* font ) @@ -1799,6 +2041,42 @@ int TTF_GetFontStyle( const TTF_Font* font ) return font->style; } +void TTF_SetFontOutline( TTF_Font* font, int outline ) +{ + font->outline = outline; + Flush_Cache( font ); +} + +int TTF_GetFontOutline( const TTF_Font* font ) +{ + return font->outline; +} + +void TTF_SetFontHinting( TTF_Font* font, int hinting ) +{ + if (hinting == TTF_HINTING_LIGHT) + font->hinting = FT_LOAD_TARGET_LIGHT; + else if (hinting == TTF_HINTING_MONO) + font->hinting = FT_LOAD_TARGET_MONO; + else if (hinting == TTF_HINTING_NONE) + font->hinting = FT_LOAD_NO_HINTING; + else + font->hinting = 0; + + Flush_Cache( font ); +} + +int TTF_GetFontHinting( const TTF_Font* font ) +{ + if (font->hinting == FT_LOAD_TARGET_LIGHT) + return TTF_HINTING_LIGHT; + else if (font->hinting == FT_LOAD_TARGET_MONO) + return TTF_HINTING_MONO; + else if (font->hinting == FT_LOAD_NO_HINTING) + return TTF_HINTING_NONE; + return 0; +} + void TTF_Quit( void ) { if ( TTF_initialized ) { @@ -1812,3 +2090,10 @@ int TTF_WasInit( void ) { return TTF_initialized; } + +int TTF_GetFontKerningSize(TTF_Font* font, int prev_index, int index) +{ + FT_Vector delta; + FT_Get_Kerning( font->face, prev_index, index, ft_kerning_default, &delta ); + return (delta.x >> 6); +} diff --git a/project/jni/sdl_ttf/glfont.c b/project/jni/sdl_ttf/glfont.c index 23f299535..5b1bfb970 100644 --- a/project/jni/sdl_ttf/glfont.c +++ b/project/jni/sdl_ttf/glfont.c @@ -1,29 +1,24 @@ /* - glfont: An example of using the SDL_ttf library with OpenGL. - Copyright (C) 1997-2004 Sam Lantinga + glfont: An example of using the SDL_ttf library with OpenGL. + Copyright (C) 2001-2012 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - The SDL_GL_* functions in this file are available in the public domain. - - Sam Lantinga - slouken@libsdl.org + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. */ -/* $Id: glfont.c 2429 2006-05-14 21:03:44Z slouken $ */ - /* A simple program to test the text rendering feature of the TTF library */ #include @@ -39,16 +34,15 @@ #define DEFAULT_PTSIZE 18 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog" -#define NUM_COLORS 256 +#define WIDTH 640 +#define HEIGHT 480 static char *Usage = "Usage: %s [-utf8|-unicode] [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] \ .ttf [ptsize] [text]\n"; -void SDL_GL_Enter2DMode() +void SDL_GL_Enter2DMode(int width, int height) { - SDL_Surface *screen = SDL_GetVideoSurface(); - /* Note, there may be other things you need to change, depending on how you have your OpenGL state set up. */ @@ -61,13 +55,13 @@ void SDL_GL_Enter2DMode() glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glViewport(0, 0, screen->w, screen->h); + glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); - glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0); + glOrtho(0.0, (GLdouble)width, (GLdouble)height, 0.0, 0.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -104,8 +98,8 @@ GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) int w, h; SDL_Surface *image; SDL_Rect area; - Uint32 saved_flags; Uint8 saved_alpha; + SDL_BlendMode saved_mode; /* Use the surface width and height expanded to powers of 2 */ w = power_of_two(surface->w); @@ -136,11 +130,10 @@ GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) } /* Save the alpha blending attributes */ - saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); - saved_alpha = surface->format->alpha; - if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { - SDL_SetAlpha(surface, 0, 0); - } + SDL_GetSurfaceAlphaMod(surface, &saved_alpha); + SDL_SetSurfaceAlphaMod(surface, 0xFF); + SDL_GetSurfaceBlendMode(surface, &saved_mode); + SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE); /* Copy the surface into the GL texture image */ area.x = 0; @@ -150,9 +143,8 @@ GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) SDL_BlitSurface(surface, &area, image, &area); /* Restore the alpha blending attributes */ - if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { - SDL_SetAlpha(surface, saved_flags, saved_alpha); - } + SDL_SetSurfaceAlphaMod(surface, saved_alpha); + SDL_SetSurfaceBlendMode(surface, saved_mode); /* Create an OpenGL texture for the image */ glGenTextures(1, &texture); @@ -182,7 +174,8 @@ static void cleanup(int exitcode) int main(int argc, char *argv[]) { char *argv0 = argv[0]; - SDL_Surface *screen; + SDL_Window *window; + SDL_GLContext context; TTF_Font *font; SDL_Surface *text; int ptsize; @@ -283,12 +276,6 @@ int main(int argc, char *argv[]) return(1); } - /* Initialize SDL */ - if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { - fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); - return(2); - } - /* Initialize the TTF library */ if ( TTF_Init() < 0 ) { fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); @@ -332,10 +319,18 @@ int main(int argc, char *argv[]) } /* Set a 640x480 video mode */ - screen = SDL_SetVideoMode(640, 480, 0, SDL_OPENGL); - if ( screen == NULL ) { - fprintf(stderr, "Couldn't set 640x480 OpenGL mode: %s\n", - SDL_GetError()); + window = SDL_CreateWindow("glfont", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + WIDTH, HEIGHT, SDL_WINDOW_OPENGL); + if ( window == NULL ) { + fprintf(stderr, "Couldn't create window: %s\n", SDL_GetError()); + cleanup(2); + } + + context = SDL_GL_CreateContext(window); + if ( context == NULL ) { + fprintf(stderr, "Couldn't create OpenGL context: %s\n", SDL_GetError()); cleanup(2); } @@ -380,8 +375,8 @@ int main(int argc, char *argv[]) TTF_CloseFont(font); cleanup(2); } - x = (screen->w - text->w)/2; - y = (screen->h - text->h)/2; + x = (WIDTH - text->w)/2; + y = (HEIGHT - text->h)/2; w = text->w; h = text->h; printf("Font is generally %d big, and string is %hd big\n", @@ -405,7 +400,7 @@ int main(int argc, char *argv[]) SDL_FreeSurface(text); /* Initialize the GL state */ - glViewport( 0, 0, screen->w, screen->h ); + glViewport( 0, 0, WIDTH, HEIGHT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); @@ -506,7 +501,7 @@ int main(int argc, char *argv[]) glRotatef(5.0, 1.0, 1.0, 1.0); /* Show the text on the screen */ - SDL_GL_Enter2DMode(); + SDL_GL_Enter2DMode(WIDTH, HEIGHT); glBindTexture(GL_TEXTURE_2D, texture); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(texMinX, texMinY); glVertex2i(x, y ); @@ -517,8 +512,9 @@ int main(int argc, char *argv[]) SDL_GL_Leave2DMode(); /* Swap the buffers so everything is visible */ - SDL_GL_SwapBuffers( ); + SDL_GL_SwapWindow(window); } + SDL_GL_DeleteContext(context); TTF_CloseFont(font); cleanup(0); diff --git a/project/jni/sdl_ttf/include/SDL_ttf.h b/project/jni/sdl_ttf/include/SDL_ttf.h index 581e3304a..224bbad3e 100644 --- a/project/jni/sdl_ttf/include/SDL_ttf.h +++ b/project/jni/sdl_ttf/include/SDL_ttf.h @@ -1,27 +1,24 @@ /* - SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts - Copyright (C) 1997-2004 Sam Lantinga + SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts + Copyright (C) 2001-2012 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. */ -/* $Id: SDL_ttf.h 3282 2007-07-15 06:02:48Z slouken $ */ - /* This library is a wrapper around the excellent FreeType 2.0 library, available at: http://www.freetype.org/ @@ -42,7 +39,7 @@ extern "C" { */ #define SDL_TTF_MAJOR_VERSION 2 #define SDL_TTF_MINOR_VERSION 0 -#define SDL_TTF_PATCHLEVEL 9 +#define SDL_TTF_PATCHLEVEL 12 /* This macro can be used to fill a version structure with the compile-time * version of the SDL_ttf library. @@ -91,16 +88,24 @@ extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndex(const char *file, int ptsiz extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontRW(SDL_RWops *src, int freesrc, int ptsize); extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIndexRW(SDL_RWops *src, int freesrc, int ptsize, long index); -/* Set and retrieve the font style - This font style is implemented by modifying the font glyphs, and - doesn't reflect any inherent properties of the truetype font file. -*/ +/* Set and retrieve the font style */ #define TTF_STYLE_NORMAL 0x00 #define TTF_STYLE_BOLD 0x01 #define TTF_STYLE_ITALIC 0x02 #define TTF_STYLE_UNDERLINE 0x04 +#define TTF_STYLE_STRIKETHROUGH 0x08 extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font); extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style); +extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline); + +/* Set and retrieve FreeType hinter settings */ +#define TTF_HINTING_NORMAL 0 +#define TTF_HINTING_LIGHT 1 +#define TTF_HINTING_MONO 2 +#define TTF_HINTING_NONE 3 +extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting); /* Get the total height of the font - usually equal to point size */ extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font); @@ -118,6 +123,10 @@ extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font); /* Get the recommended spacing between lines of text for this font */ extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font); +/* Get/Set whether or not kerning is allowed for this font */ +extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font); +extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed); + /* Get the number of faces of the font */ extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font); @@ -126,6 +135,9 @@ extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font); extern DECLSPEC char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font); extern DECLSPEC char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font); +/* Check wether a glyph is provided by the font or not */ +extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch); + /* Get the metrics (dimensions) of a glyph To understand what these metrics mean, here is a useful link: http://freetype.sourceforge.net/freetype2/docs/tutorial/step2.html @@ -221,6 +233,9 @@ extern DECLSPEC void SDLCALL TTF_Quit(void); /* Check if the TTF engine is initialized */ extern DECLSPEC int SDLCALL TTF_WasInit(void); +/* Get the kerning size of two glyphs */ +extern DECLSPEC int TTF_GetFontKerningSize(TTF_Font *font, int prev_index, int index); + /* We'll use SDL for reporting errors */ #define TTF_SetError SDL_SetError #define TTF_GetError SDL_GetError diff --git a/project/jni/sdl_ttf/showfont.c b/project/jni/sdl_ttf/showfont.c index ac39fee70..9c8a595c5 100644 --- a/project/jni/sdl_ttf/showfont.c +++ b/project/jni/sdl_ttf/showfont.c @@ -1,27 +1,24 @@ /* - showfont: An example of using the SDL_ttf library with 2D graphics. - Copyright (C) 1997-2004 Sam Lantinga + showfont: An example of using the SDL_ttf library with 2D graphics. + Copyright (C) 2001-2012 Sam Lantinga - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. */ -/* $Id: showfont.c 2429 2006-05-14 21:03:44Z slouken $ */ - /* A simple program to test the text rendering feature of the TTF library */ #include @@ -38,9 +35,29 @@ #define DEFAULT_PTSIZE 18 #define DEFAULT_TEXT "The quick brown fox jumped over the lazy dog" #define NUM_COLORS 256 +#define WIDTH 640 +#define HEIGHT 480 static char *Usage = -"Usage: %s [-solid] [-utf8|-unicode] [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] .ttf [ptsize] [text]\n"; +"Usage: %s [-solid] [-utf8|-unicode] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-fgcol r,g,b] [-bgcol r,g,b] .ttf [ptsize] [text]\n"; + +typedef struct { + SDL_Texture *caption; + SDL_Rect captionRect; + SDL_Texture *message; + SDL_Rect messageRect; +} Scene; + +static void draw_scene(SDL_Renderer *renderer, Scene *scene) +{ + /* Clear the background to background color */ + SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF); + SDL_RenderClear(renderer); + + SDL_RenderCopy(renderer, scene->caption, NULL, &scene->captionRect); + SDL_RenderCopy(renderer, scene->message, NULL, &scene->messageRect); + SDL_RenderPresent(renderer); +} static void cleanup(int exitcode) { @@ -52,21 +69,23 @@ static void cleanup(int exitcode) int main(int argc, char *argv[]) { char *argv0 = argv[0]; - SDL_Surface *screen; + SDL_Window *window; + SDL_Renderer *renderer; TTF_Font *font; - SDL_Surface *text, *temp; + SDL_Surface *text; + Scene scene; int ptsize; int i, done; - int rdiff, gdiff, bdiff; - SDL_Color colors[NUM_COLORS]; SDL_Color white = { 0xFF, 0xFF, 0xFF, 0 }; SDL_Color black = { 0x00, 0x00, 0x00, 0 }; SDL_Color *forecol; SDL_Color *backcol; - SDL_Rect dstrect; SDL_Event event; int rendersolid; int renderstyle; + int outline; + int hinting; + int kerning; int dump; enum { RENDER_LATIN1, @@ -81,6 +100,9 @@ int main(int argc, char *argv[]) rendersolid = 0; renderstyle = TTF_STYLE_NORMAL; rendertype = RENDER_LATIN1; + outline = 0; + hinting = TTF_HINTING_NORMAL; + kerning = 1; /* Default is black and white */ forecol = &black; backcol = &white; @@ -103,6 +125,27 @@ int main(int argc, char *argv[]) if ( strcmp(argv[i], "-u") == 0 ) { renderstyle |= TTF_STYLE_UNDERLINE; } else + if ( strcmp(argv[i], "-s") == 0 ) { + renderstyle |= TTF_STYLE_STRIKETHROUGH; + } else + if ( strcmp(argv[i], "-outline") == 0 ) { + if ( sscanf (argv[++i], "%d", &outline) != 1 ) { + fprintf(stderr, Usage, argv0); + return(1); + } + } else + if ( strcmp(argv[i], "-hintlight") == 0 ) { + hinting = TTF_HINTING_LIGHT; + } else + if ( strcmp(argv[i], "-hintmono") == 0 ) { + hinting = TTF_HINTING_MONO; + } else + if ( strcmp(argv[i], "-hintnone") == 0 ) { + hinting = TTF_HINTING_NONE; + } else + if ( strcmp(argv[i], "-nokerning") == 0 ) { + kerning = 0; + } else if ( strcmp(argv[i], "-dump") == 0 ) { dump = 1; } else @@ -139,12 +182,6 @@ int main(int argc, char *argv[]) return(1); } - /* Initialize SDL */ - if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { - fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError()); - return(2); - } - /* Initialize the TTF library */ if ( TTF_Init() < 0 ) { fprintf(stderr, "Couldn't initialize TTF: %s\n",SDL_GetError()); @@ -170,6 +207,9 @@ int main(int argc, char *argv[]) cleanup(2); } TTF_SetFontStyle(font, renderstyle); + TTF_SetFontOutline(font, outline); + TTF_SetFontKerning(font, kerning); + TTF_SetFontHinting(font, hinting); if( dump ) { for( i = 48; i < 123; i++ ) { @@ -187,30 +227,12 @@ int main(int argc, char *argv[]) cleanup(0); } - /* Set a 640x480x8 video mode */ - screen = SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); - if ( screen == NULL ) { - fprintf(stderr, "Couldn't set 640x480x8 video mode: %s\n", - SDL_GetError()); + /* Create a window */ + if (SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, 0, &window, &renderer) < 0) { + fprintf(stderr, "SDL_CreateWindowAndRenderer() failed: %s\n", SDL_GetError()); cleanup(2); } - /* Set a palette that is good for the foreground colored text */ - rdiff = backcol->r - forecol->r; - gdiff = backcol->g - forecol->g; - bdiff = backcol->b - forecol->b; - for ( i=0; ir + (i*rdiff)/4; - colors[i].g = forecol->g + (i*gdiff)/4; - colors[i].b = forecol->b + (i*bdiff)/4; - } - SDL_SetColors(screen, colors, 0, NUM_COLORS); - - /* Clear the background to background color */ - SDL_FillRect(screen, NULL, - SDL_MapRGB(screen->format, backcol->r, backcol->g, backcol->b)); - SDL_UpdateRect(screen, 0, 0, 0, 0); - /* Show which font file we're looking at */ sprintf(string, "Font file: %s", argv[0]); /* possible overflow */ if ( rendersolid ) { @@ -219,11 +241,11 @@ int main(int argc, char *argv[]) text = TTF_RenderText_Shaded(font, string, *forecol, *backcol); } if ( text != NULL ) { - dstrect.x = 4; - dstrect.y = 4; - dstrect.w = text->w; - dstrect.h = text->h; - SDL_BlitSurface(text, NULL, screen, &dstrect); + scene.captionRect.x = 4; + scene.captionRect.y = 4; + scene.captionRect.w = text->w; + scene.captionRect.h = text->h; + scene.caption = SDL_CreateTextureFromSurface(renderer, text); SDL_FreeSurface(text); } @@ -306,32 +328,15 @@ int main(int argc, char *argv[]) TTF_CloseFont(font); cleanup(2); } - dstrect.x = (screen->w - text->w)/2; - dstrect.y = (screen->h - text->h)/2; - dstrect.w = text->w; - dstrect.h = text->h; + scene.messageRect.x = (WIDTH - text->w)/2; + scene.messageRect.y = (HEIGHT - text->h)/2; + scene.messageRect.w = text->w; + scene.messageRect.h = text->h; + scene.message = SDL_CreateTextureFromSurface(renderer, text); printf("Font is generally %d big, and string is %hd big\n", TTF_FontHeight(font), text->h); - /* Blit the text surface */ - if ( SDL_BlitSurface(text, NULL, screen, &dstrect) < 0 ) { - fprintf(stderr, "Couldn't blit text to display: %s\n", - SDL_GetError()); - TTF_CloseFont(font); - cleanup(2); - } - SDL_UpdateRect(screen, 0, 0, 0, 0); - - /* Set the text colorkey and convert to display format */ - if ( SDL_SetColorKey(text, SDL_SRCCOLORKEY|SDL_RLEACCEL, 0) < 0 ) { - fprintf(stderr, "Warning: Couldn't set text colorkey: %s\n", - SDL_GetError()); - } - temp = SDL_DisplayFormat(text); - if ( temp != NULL ) { - SDL_FreeSurface(text); - text = temp; - } + draw_scene(renderer, &scene); /* Wait for a keystroke, and blit text on mouse press */ done = 0; @@ -344,18 +349,11 @@ int main(int argc, char *argv[]) } switch (event.type) { case SDL_MOUSEBUTTONDOWN: - dstrect.x = event.button.x - text->w/2; - dstrect.y = event.button.y - text->h/2; - dstrect.w = text->w; - dstrect.h = text->h; - if ( SDL_BlitSurface(text, NULL, screen, - &dstrect) == 0 ) { - SDL_UpdateRects(screen, 1, &dstrect); - } else { - fprintf(stderr, - "Couldn't blit text to display: %s\n", - SDL_GetError()); - } + scene.messageRect.x = event.button.x - text->w/2; + scene.messageRect.y = event.button.y - text->h/2; + scene.messageRect.w = text->w; + scene.messageRect.h = text->h; + draw_scene(renderer, &scene); break; case SDL_KEYDOWN: @@ -368,6 +366,8 @@ int main(int argc, char *argv[]) } SDL_FreeSurface(text); TTF_CloseFont(font); + SDL_DestroyTexture(scene.caption); + SDL_DestroyTexture(scene.message); cleanup(0); /* Not reached, but fixes compiler warnings */