--- /dev/null
+diff -durN SDL_ttf-2.0.6.orig/SDL_ttf.c SDL_ttf-2.0.6/SDL_ttf.c
+--- SDL_ttf-2.0.6.orig/SDL_ttf.c 2003-02-21 17:38:15.000000000 +0000
++++ SDL_ttf-2.0.6/SDL_ttf.c 2004-12-29 11:18:02.473824704 +0000
+@@ -39,6 +39,7 @@
+ #define FREEA(p) free(p)
+ #endif
+
++#include <ft2build.h>
+ #include <freetype/freetype.h>
+ #include <freetype/ftoutln.h>
+ #include <freetype/ttnameid.h>
+diff -durN SDL_ttf-2.0.6.orig/SDL_ttf.c~ SDL_ttf-2.0.6/SDL_ttf.c~
+--- SDL_ttf-2.0.6.orig/SDL_ttf.c~ 1970-01-01 00:00:00.000000000 +0000
++++ SDL_ttf-2.0.6/SDL_ttf.c~ 2003-02-21 17:38:15.000000000 +0000
+@@ -0,0 +1,1628 @@
++/*
++ SDL_ttf: A companion library to SDL for working with TrueType (tm) fonts
++ Copyright (C) 1997, 1998, 1999, 2000, 2001 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 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.
++
++ 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
++*/
++
++/* $Id$ */
++
++#include <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#ifdef HAVE_ALLOCA_H
++#include <alloca.h>
++#endif
++
++#ifdef HAVE_ALLOCA
++#define ALLOCA(n) ((void*)alloca(n))
++#define FREEA(p)
++#else
++#define ALLOCA(n) malloc(n)
++#define FREEA(p) free(p)
++#endif
++
++#include <freetype/freetype.h>
++#include <freetype/ftoutln.h>
++#include <freetype/ttnameid.h>
++#include <freetype/internal/ftobjs.h>
++
++#include "SDL.h"
++#include "SDL_endian.h"
++#include "SDL_ttf.h"
++
++/* FIXME: Right now we assume the gray-scale renderer Freetype is using
++ supports 256 shades of gray, but we should instead key off of num_grays
++ in the result FT_Bitmap after the FT_Render_Glyph() call. */
++#define NUM_GRAYS 256
++
++/* Handy routines for converting from fixed point */
++#define FT_FLOOR(X) ((X & -64) / 64)
++#define FT_CEIL(X) (((X + 63) & -64) / 64)
++
++#define CACHED_METRICS 0x10
++#define CACHED_BITMAP 0x01
++#define CACHED_PIXMAP 0x02
++
++/* Cached glyph information */
++typedef struct cached_glyph {
++ int stored;
++ FT_UInt index;
++ FT_Bitmap bitmap;
++ FT_Bitmap pixmap;
++ int minx;
++ int maxx;
++ int miny;
++ int maxy;
++ int yoffset;
++ int advance;
++ Uint16 cached;
++} c_glyph;
++
++/* The structure used to hold internal font information */
++struct _TTF_Font {
++ /* Freetype2 maintains all sorts of useful info itself */
++ FT_Face face;
++
++ /* We'll cache these ourselves */
++ int height;
++ int ascent;
++ int descent;
++ int lineskip;
++
++ /* The font style */
++ int style;
++
++ /* Extra width in glyph bounds for text styles */
++ int glyph_overhang;
++ float glyph_italics;
++
++ /* Information in the font for underlining */
++ int underline_offset;
++ int underline_height;
++
++ /* Cache for style-transformed glyphs */
++ c_glyph *current;
++ c_glyph cache[256];
++ c_glyph scratch;
++
++ /* We are responsible for closing the font stream */
++ SDL_RWops *src;
++ int freesrc;
++ FT_Open_Args args;
++
++ /* For non-scalable formats, we must remember which font index size */
++ int font_size_family;
++};
++
++/* 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)
++{
++ int size = 0;
++ while ( *text++ ) {
++ ++size;
++ }
++ return size;
++}
++static __inline__ void UNICODE_strcpy(Uint16 *dst, const Uint16 *src, int swap)
++{
++ if ( swap ) {
++ while ( *src ) {
++ *dst = SDL_Swap16(*src);
++ ++src;
++ ++dst;
++ }
++ *dst = '\0';
++ } else {
++ while ( *src ) {
++ *dst = *src;
++ ++src;
++ ++dst;
++ }
++ *dst = '\0';
++ }
++}
++
++/* rcg06192001 get linked library's version. */
++const SDL_version *TTF_Linked_Version(void)
++{
++ static SDL_version linked_version;
++ TTF_VERSION(&linked_version);
++ return(&linked_version);
++}
++
++/* This function tells the library whether UNICODE text is generally
++ byteswapped. A UNICODE BOM character at the beginning of a string
++ will override this setting for that string.
++ */
++void TTF_ByteSwappedUNICODE(int swapped)
++{
++ TTF_byteswapped = swapped;
++}
++
++static void TTF_SetFTError(const char *msg, FT_Error error)
++{
++#ifdef USE_FREETYPE_ERRORS
++#undef FTERRORS_H
++#define FT_ERRORDEF( e, v, s ) { e, s },
++ static const struct
++ {
++ int err_code;
++ const char* err_msg;
++ } ft_errors[] = {
++#include <freetype/fterrors.h>
++ };
++ int i;
++ const char *err_msg;
++ char buffer[1024];
++
++ err_msg = NULL;
++ for ( i=0; i<((sizeof ft_errors)/(sizeof ft_errors[0])); ++i ) {
++ if ( error == ft_errors[i].err_code ) {
++ err_msg = ft_errors[i].err_msg;
++ break;
++ }
++ }
++ if ( ! err_msg ) {
++ err_msg = "unknown FreeType error";
++ }
++ sprintf(buffer, "%s: %s", msg, err_msg);
++ TTF_SetError(buffer);
++#else
++ TTF_SetError(msg);
++#endif /* USE_FREETYPE_ERRORS */
++}
++
++int TTF_Init( void )
++{
++ int status = 0;
++
++ if ( ! TTF_initialized ) {
++ FT_Error error = FT_Init_FreeType( &library );
++ if ( error ) {
++ TTF_SetFTError("Couldn't init FreeType engine", error);
++ status = -1;
++ }
++ }
++ if ( status == 0 ) {
++ ++TTF_initialized;
++ }
++ return status;
++}
++
++static unsigned long RWread(
++ FT_Stream stream,
++ unsigned long offset,
++ unsigned char* buffer,
++ unsigned long count
++)
++{
++ SDL_RWops *src;
++
++ src = (SDL_RWops *)stream->descriptor.pointer;
++ SDL_RWseek( src, (int)offset, SEEK_SET );
++ return SDL_RWread( src, buffer, 1, (int)count );
++}
++
++TTF_Font* TTF_OpenFontIndexRW( SDL_RWops *src, int freesrc, int ptsize, long index )
++{
++ TTF_Font* font;
++ FT_Error error;
++ FT_Face face;
++ FT_Fixed scale;
++ FT_Stream stream;
++ int position;
++
++ if ( ! TTF_initialized ) {
++ TTF_SetError( "Library not initialized" );
++ return NULL;
++ }
++
++ /* Check to make sure we can seek in this stream */
++ position = SDL_RWtell(src);
++ if ( position < 0 ) {
++ TTF_SetError( "Can't seek in stream" );
++ return NULL;
++ }
++
++ font = (TTF_Font*) malloc(sizeof *font);
++ if ( font == NULL ) {
++ TTF_SetError( "Out of memory" );
++ return NULL;
++ }
++ memset(font, 0, sizeof(*font));
++
++ font->src = src;
++ font->freesrc = freesrc;
++
++ stream = (FT_Stream)malloc(sizeof(*stream));
++ if ( stream == NULL ) {
++ TTF_SetError( "Out of memory" );
++ TTF_CloseFont( font );
++ return NULL;
++ }
++ memset(stream, 0, sizeof(*stream));
++
++ stream->memory = library->memory;
++ stream->read = RWread;
++ stream->descriptor.pointer = src;
++ stream->pos = (unsigned long)position;
++ SDL_RWseek(src, 0, SEEK_END);
++ stream->size = (unsigned long)(SDL_RWtell(src) - position);
++ SDL_RWseek(src, position, SEEK_SET);
++
++ font->args.flags = ft_open_stream;
++ font->args.stream = stream;
++
++ error = FT_Open_Face( library, &font->args, index, &font->face );
++ if( error ) {
++ TTF_SetFTError( "Couldn't load font file", error );
++ TTF_CloseFont( font );
++ return NULL;
++ }
++ face = font->face;
++
++ /* Make sure that our font face is scalable (global metrics) */
++ if ( FT_IS_SCALABLE(face) ) {
++
++ /* Set the character size and use default DPI (72) */
++ error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 );
++ if( error ) {
++ TTF_SetFTError( "Couldn't set font size", error );
++ TTF_CloseFont( font );
++ return NULL;
++ }
++
++ /* Get the scalable font metrics for this font */
++ scale = face->size->metrics.y_scale;
++ font->ascent = FT_CEIL(FT_MulFix(face->bbox.yMax, scale));
++ font->descent = FT_CEIL(FT_MulFix(face->bbox.yMin, scale));
++ font->height = font->ascent - font->descent + /* baseline */ 1;
++ font->lineskip = FT_CEIL(FT_MulFix(face->height, scale));
++ font->underline_offset = FT_FLOOR(FT_MulFix(face->underline_position, scale));
++ font->underline_height = FT_FLOOR(FT_MulFix(face->underline_thickness, scale));
++
++ } else {
++ /* Non-scalable font case. ptsize determines which family
++ * or series of fonts to grab from the non-scalable format.
++ * It is not the point size of the font.
++ * */
++ if ( ptsize >= font->face->num_fixed_sizes )
++ ptsize = font->face->num_fixed_sizes - 1;
++ font->font_size_family = ptsize;
++ error = FT_Set_Pixel_Sizes( face,
++ face->available_sizes[ptsize].height,
++ face->available_sizes[ptsize].width );
++ /* With non-scalale fonts, Freetype2 likes to fill many of the
++ * font metrics with the value of 0. The size of the
++ * non-scalable fonts must be determined differently
++ * or sometimes cannot be determined.
++ * */
++ font->ascent = face->available_sizes[ptsize].height;
++ font->descent = 0;
++ font->height = face->available_sizes[ptsize].height;
++ font->lineskip = FT_CEIL(font->ascent);
++ font->underline_offset = FT_FLOOR(face->underline_position);
++ font->underline_height = FT_FLOOR(face->underline_thickness);
++ }
++
++ if ( font->underline_height < 1 ) {
++ font->underline_height = 1;
++ }
++
++#ifdef DEBUG_FONTS
++ printf("Font metrics:\n");
++ printf("\tascent = %d, descent = %d\n",
++ font->ascent, font->descent);
++ printf("\theight = %d, lineskip = %d\n",
++ font->height, font->lineskip);
++ printf("\tunderline_offset = %d, underline_height = %d\n",
++ font->underline_offset, font->underline_height);
++#endif
++
++ /* Set the default font style */
++ font->style = TTF_STYLE_NORMAL;
++ 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;
++ font->glyph_italics *= font->height;
++
++ return font;
++}
++
++TTF_Font* TTF_OpenFontRW( SDL_RWops *src, int freesrc, int ptsize )
++{
++ return TTF_OpenFontIndexRW(src, freesrc, ptsize, 0);
++}
++
++TTF_Font* TTF_OpenFontIndex( const char *file, int ptsize, long index )
++{
++ return TTF_OpenFontIndexRW(SDL_RWFromFile(file, "rb"), 1, ptsize, index);
++}
++
++TTF_Font* TTF_OpenFont( const char *file, int ptsize )
++{
++ return TTF_OpenFontIndex(file, ptsize, 0);
++}
++
++static void Flush_Glyph( c_glyph* glyph )
++{
++ glyph->stored = 0;
++ glyph->index = 0;
++ if( glyph->bitmap.buffer ) {
++ free( glyph->bitmap.buffer );
++ glyph->bitmap.buffer = 0;
++ }
++ if( glyph->pixmap.buffer ) {
++ free( glyph->pixmap.buffer );
++ glyph->pixmap.buffer = 0;
++ }
++ glyph->cached = 0;
++}
++
++static void Flush_Cache( TTF_Font* font )
++{
++ int i;
++ int size = sizeof( font->cache ) / sizeof( font->cache[0] );
++
++ for( i = 0; i < size; ++i ) {
++ if( font->cache[i].cached ) {
++ Flush_Glyph( &font->cache[i] );
++ }
++
++ }
++ if( font->scratch.cached ) {
++ Flush_Glyph( &font->scratch );
++ }
++
++}
++
++static FT_Error Load_Glyph( TTF_Font* font, Uint16 ch, c_glyph* cached, int want )
++{
++ FT_Face face;
++ FT_Error error;
++ FT_GlyphSlot glyph;
++ FT_Glyph_Metrics* metrics;
++ FT_Outline* outline;
++
++ if ( !font || !font->face ) {
++ return FT_Err_Invalid_Handle;
++ }
++
++ face = font->face;
++
++ /* Load the glyph */
++ if ( ! cached->index ) {
++ cached->index = FT_Get_Char_Index( face, ch );
++ }
++ error = FT_Load_Glyph( face, cached->index, FT_LOAD_DEFAULT );
++ if( error ) {
++ return error;
++ }
++
++ /* Get our glyph shortcuts */
++ glyph = face->glyph;
++ metrics = &glyph->metrics;
++ outline = &glyph->outline;
++
++ /* Get the glyph metrics if desired */
++ if ( (want & CACHED_METRICS) && !(cached->stored & CACHED_METRICS) ) {
++ if ( FT_IS_SCALABLE( face ) ) {
++ /* Get the bounding box */
++ cached->minx = FT_FLOOR(metrics->horiBearingX);
++ cached->maxx = cached->minx + FT_CEIL(metrics->width);
++ cached->maxy = FT_FLOOR(metrics->horiBearingY);
++ cached->miny = cached->maxy - FT_CEIL(metrics->height);
++ cached->yoffset = font->ascent - cached->maxy;
++ cached->advance = FT_CEIL(metrics->horiAdvance);
++ } else {
++ /* Get the bounding box for non-scalable format.
++ * Again, freetype2 fills in many of the font metrics
++ * with the value of 0, so some of the values we
++ * need must be calculated differently with certain
++ * assumptions about non-scalable formats.
++ * */
++ cached->minx = FT_FLOOR(metrics->horiBearingX);
++ cached->maxx = cached->minx + FT_CEIL(metrics->horiAdvance);
++ cached->maxy = FT_FLOOR(metrics->horiBearingY);
++ cached->miny = cached->maxy - FT_CEIL(face->available_sizes[font->font_size_family].height);
++ cached->yoffset = 0;
++ cached->advance = FT_CEIL(metrics->horiAdvance);
++ }
++
++ /* Adjust for bold and italic text */
++ if( font->style & TTF_STYLE_BOLD ) {
++ cached->maxx += font->glyph_overhang;
++ }
++ if( font->style & TTF_STYLE_ITALIC ) {
++ cached->maxx += (int)ceil(font->glyph_italics);
++ }
++ cached->stored |= CACHED_METRICS;
++ }
++
++ if ( ((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
++ ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ) {
++ int mono = (want & CACHED_BITMAP);
++ int i;
++ FT_Bitmap* src;
++ FT_Bitmap* dst;
++
++ /* Handle the italic style */
++ if( font->style & TTF_STYLE_ITALIC ) {
++ FT_Matrix shear;
++
++ shear.xx = 1 << 16;
++ shear.xy = (int) ( font->glyph_italics * ( 1 << 16 ) ) / font->height;
++ shear.yx = 0;
++ shear.yy = 1 << 16;
++
++ FT_Outline_Transform( outline, &shear );
++ }
++
++ /* Render the glyph */
++ if ( mono ) {
++ error = FT_Render_Glyph( glyph, ft_render_mode_mono );
++ } else {
++ error = FT_Render_Glyph( glyph, ft_render_mode_normal );
++ }
++ if( error ) {
++ return error;
++ }
++
++ /* Copy over information to cache */
++ src = &glyph->bitmap;
++ if ( mono ) {
++ dst = &cached->bitmap;
++ } else {
++ dst = &cached->pixmap;
++ }
++ memcpy( dst, src, sizeof( *dst ) );
++
++ /* FT_Render_Glyph() and .fon fonts always generate a
++ * two-color (black and white) glyphslot surface, even
++ * when rendered in ft_render_mode_normal. This is probably
++ * a freetype2 bug because it is inconsistent with the
++ * freetype2 documentation under FT_Render_Mode section.
++ * */
++ if ( mono || !FT_IS_SCALABLE(face) ) {
++ dst->pitch *= 8;
++ }
++
++ /* Adjust for bold and italic text */
++ if( font->style & TTF_STYLE_BOLD ) {
++ int bump = font->glyph_overhang;
++ dst->pitch += bump;
++ dst->width += bump;
++ }
++ if( font->style & TTF_STYLE_ITALIC ) {
++ int bump = (int)ceil(font->glyph_italics);
++ dst->pitch += bump;
++ dst->width += bump;
++ }
++
++ if (dst->rows != 0) {
++ dst->buffer = malloc( dst->pitch * dst->rows );
++ if( !dst->buffer ) {
++ return FT_Err_Out_Of_Memory;
++ }
++ memset( dst->buffer, 0, dst->pitch * dst->rows );
++
++ for( i = 0; i < src->rows; i++ ) {
++ int soffset = i * src->pitch;
++ int doffset = i * dst->pitch;
++ if ( mono ) {
++ unsigned char *srcp = src->buffer + soffset;
++ unsigned char *dstp = dst->buffer + doffset;
++ int j;
++ 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;
++ }
++ } else if ( !FT_IS_SCALABLE(face) ) {
++ /* This special case wouldn't
++ * be here if the FT_Render_Glyph()
++ * function wasn't buggy when it tried
++ * to render a .fon font with 256
++ * shades of gray. Instead, it
++ * returns a black and white surface
++ * and we have to translate it back
++ * to a 256 gray shaded surface.
++ * */
++ unsigned char *srcp = src->buffer + soffset;
++ unsigned char *dstp = dst->buffer + doffset;
++ unsigned char ch;
++ int j, k;
++ for ( j = 0; j < src->width; j += 8) {
++ ch = *srcp++;
++ for (k = 0; k < 8; ++k) {
++ if ((ch&0x80) >> 7) {
++ *dstp++ = NUM_GRAYS - 1;
++ } else {
++ *dstp++ = 0x00;
++ }
++ ch <<= 1;
++ }
++ }
++ } else {
++ memcpy(dst->buffer+doffset,
++ src->buffer+soffset, src->pitch);
++ }
++ }
++ }
++
++ /* Handle the bold style */
++ if ( font->style & TTF_STYLE_BOLD ) {
++ int row;
++ int col;
++ int offset;
++ int pixel;
++ Uint8* pixmap;
++
++ /* The pixmap is a little hard, we have to add and clamp */
++ for( row = dst->rows - 1; row >= 0; --row ) {
++ pixmap = (Uint8*) dst->buffer + row * dst->pitch;
++ for( offset=1; offset <= font->glyph_overhang; ++offset ) {
++ for( col = dst->width - 1; col > 0; --col ) {
++ pixel = (pixmap[col] + pixmap[col-1]);
++ if( pixel > NUM_GRAYS - 1 ) {
++ pixel = NUM_GRAYS - 1;
++ }
++ pixmap[col] = (Uint8) pixel;
++ }
++ }
++ }
++ }
++
++ /* Mark that we rendered this format */
++ if ( mono ) {
++ cached->stored |= CACHED_BITMAP;
++ } else {
++ cached->stored |= CACHED_PIXMAP;
++ }
++ }
++
++ /* We're done, mark this glyph cached */
++ cached->cached = ch;
++
++ return 0;
++}
++
++static FT_Error Find_Glyph( TTF_Font* font, Uint16 ch, int want )
++{
++ int retval = 0;
++
++ 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 );
++ }
++ return retval;
++}
++
++void TTF_CloseFont( TTF_Font* font )
++{
++ Flush_Cache( font );
++ if ( font->face ) {
++ FT_Done_Face( font->face );
++ }
++ if ( font->args.stream ) {
++ free( font->args.stream );
++ }
++ if ( font->freesrc ) {
++ SDL_RWclose( font->src );
++ }
++ free( font );
++}
++
++static Uint16 *LATIN1_to_UNICODE(Uint16 *unicode, const char *text, int len)
++{
++ int i;
++
++ for ( i=0; i < len; ++i ) {
++ unicode[i] = ((const unsigned char *)text)[i];
++ }
++ unicode[i] = 0;
++
++ return unicode;
++}
++
++static Uint16 *UTF8_to_UNICODE(Uint16 *unicode, const char *utf8, int len)
++{
++ int i, j;
++ Uint16 ch;
++
++ for ( i=0, j=0; i < len; ++i, ++j ) {
++ ch = ((const unsigned char *)utf8)[i];
++ if ( ch >= 0xF0 ) {
++ ch = (Uint16)(utf8[i]&0x07) << 18;
++ ch |= (Uint16)(utf8[++i]&0x3F) << 12;
++ ch |= (Uint16)(utf8[++i]&0x3F) << 6;
++ ch |= (Uint16)(utf8[++i]&0x3F);
++ } else
++ if ( ch >= 0xE0 ) {
++ ch = (Uint16)(utf8[i]&0x3F) << 12;
++ ch |= (Uint16)(utf8[++i]&0x3F) << 6;
++ ch |= (Uint16)(utf8[++i]&0x3F);
++ } else
++ if ( ch >= 0xC0 ) {
++ ch = (Uint16)(utf8[i]&0x3F) << 6;
++ ch |= (Uint16)(utf8[++i]&0x3F);
++ }
++ unicode[j] = ch;
++ }
++ unicode[j] = 0;
++
++ return unicode;
++}
++
++int TTF_FontHeight(TTF_Font *font)
++{
++ return(font->height);
++}
++
++int TTF_FontAscent(TTF_Font *font)
++{
++ return(font->ascent);
++}
++
++int TTF_FontDescent(TTF_Font *font)
++{
++ return(font->descent);
++}
++
++int TTF_FontLineSkip(TTF_Font *font)
++{
++ return(font->lineskip);
++}
++
++long TTF_FontFaces(TTF_Font *font)
++{
++ return(font->face->num_faces);
++}
++
++int TTF_FontFaceIsFixedWidth(TTF_Font *font)
++{
++ return(FT_IS_FIXED_WIDTH(font->face));
++}
++
++char *TTF_FontFaceFamilyName(TTF_Font *font)
++{
++ return(font->face->family_name);
++}
++
++char *TTF_FontFaceStyleName(TTF_Font *font)
++{
++ return(font->face->style_name);
++}
++
++int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
++ int* minx, int* maxx, int* miny, int* maxy, int* advance)
++{
++ FT_Error error;
++
++ error = Find_Glyph(font, ch, CACHED_METRICS);
++ if ( error ) {
++ TTF_SetFTError("Couldn't find glyph", error);
++ return -1;
++ }
++
++ if ( minx ) {
++ *minx = font->current->minx;
++ }
++ if ( maxx ) {
++ *maxx = font->current->maxx;
++ }
++ if ( miny ) {
++ *miny = font->current->miny;
++ }
++ if ( maxy ) {
++ *maxy = font->current->maxy;
++ }
++ if ( advance ) {
++ *advance = font->current->advance;
++ }
++ return 0;
++}
++
++int TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h)
++{
++ Uint16 *unicode_text;
++ int unicode_len;
++ int status;
++
++ /* Copy the Latin-1 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return -1;
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ status = TTF_SizeUNICODE(font, unicode_text, w, h);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return status;
++}
++
++int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h)
++{
++ Uint16 *unicode_text;
++ int unicode_len;
++ int status;
++
++ /* Copy the UTF-8 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return -1;
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ status = TTF_SizeUNICODE(font, unicode_text, w, h);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return status;
++}
++
++int TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h)
++{
++ int status;
++ const Uint16 *ch;
++ int swapped;
++ int x, z;
++ int minx, maxx;
++ int miny, maxy;
++ c_glyph *glyph;
++ FT_Error error;
++
++ /* Initialize everything to 0 */
++ if ( ! TTF_initialized ) {
++ TTF_SetError( "Library not initialized" );
++ return -1;
++ }
++ status = 0;
++ minx = maxx = 0;
++ miny = maxy = 0;
++ swapped = TTF_byteswapped;
++
++ /* Load each character and sum it's bounding box */
++ x= 0;
++ for ( ch=text; *ch; ++ch ) {
++ Uint16 c = *ch;
++ if ( c == UNICODE_BOM_NATIVE ) {
++ swapped = 0;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( c == UNICODE_BOM_SWAPPED ) {
++ swapped = 1;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( swapped ) {
++ c = SDL_Swap16(c);
++ }
++
++ error = Find_Glyph(font, c, CACHED_METRICS);
++ if ( error ) {
++ return -1;
++ }
++ glyph = font->current;
++
++ if ( (ch == text) && (glyph->minx < 0) ) {
++ /* Fixes the texture wrapping bug when the first letter
++ * has a negative minx value or horibearing value. The entire
++ * bounding box must be adjusted to be bigger so the entire
++ * letter can fit without any texture corruption or wrapping.
++ *
++ * Effects: First enlarges bounding box.
++ * Second, xstart has to start ahead of its normal spot in the
++ * negative direction of the negative minx value.
++ * (pushes everything to the right).
++ *
++ * This will make the memory copy of the glyph bitmap data
++ * work out correctly.
++ * */
++ z -= glyph->minx;
++
++ }
++
++ z = x + glyph->minx;
++ if ( minx > z ) {
++ minx = z;
++ }
++ if ( font->style & TTF_STYLE_BOLD ) {
++ x += font->glyph_overhang;
++ }
++ if ( glyph->advance > glyph->maxx ) {
++ z = x + glyph->advance;
++ } else {
++ z = x + glyph->maxx;
++ }
++ if ( maxx < z ) {
++ maxx = z;
++ }
++ x += glyph->advance;
++
++ if ( glyph->miny < miny ) {
++ miny = glyph->miny;
++ }
++ if ( glyph->maxy > maxy ) {
++ maxy = glyph->maxy;
++ }
++ }
++
++ /* Fill the bounds rectangle */
++ if ( w ) {
++ *w = (maxx - minx);
++ }
++ if ( h ) {
++#if 0 /* This is correct, but breaks many applications */
++ *h = (maxy - miny);
++#else
++ *h = font->height;
++#endif
++ }
++ return status;
++}
++
++/* Convert the Latin-1 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderText_Solid(TTF_Font *font,
++ const char *text, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the Latin-1 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++/* Convert the UTF-8 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderUTF8_Solid(TTF_Font *font,
++ const char *text, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the UTF-8 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ UTF8_to_UNICODE(unicode_text, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++SDL_Surface *TTF_RenderUNICODE_Solid(TTF_Font *font,
++ const Uint16 *text, SDL_Color fg)
++{
++ int xstart;
++ int width;
++ int height;
++ SDL_Surface* textbuf;
++ SDL_Palette* palette;
++ const Uint16* ch;
++ Uint8* src;
++ Uint8* dst;
++ int swapped;
++ int row, col;
++ c_glyph *glyph;
++ FT_Bitmap *current;
++ FT_Error error;
++
++ /* Get the dimensions of the text surface */
++ if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 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);
++ if( textbuf == NULL ) {
++ return NULL;
++ }
++
++ /* Fill the palette with the foreground color */
++ palette = textbuf->format->palette;
++ palette->colors[0].r = 255 - fg.r;
++ palette->colors[0].g = 255 - fg.g;
++ palette->colors[0].b = 255 - fg.b;
++ palette->colors[1].r = fg.r;
++ palette->colors[1].g = fg.g;
++ palette->colors[1].b = fg.b;
++ SDL_SetColorKey( textbuf, SDL_SRCCOLORKEY, 0 );
++
++ /* Load and render each character */
++ xstart = 0;
++ swapped = TTF_byteswapped;
++ for( ch=text; *ch; ++ch ) {
++ Uint16 c = *ch;
++ if ( c == UNICODE_BOM_NATIVE ) {
++ swapped = 0;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( c == UNICODE_BOM_SWAPPED ) {
++ swapped = 1;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( swapped ) {
++ c = SDL_Swap16(c);
++ }
++
++ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_BITMAP);
++ if( error ) {
++ SDL_FreeSurface( textbuf );
++ return NULL;
++ }
++ glyph = font->current;
++ current = &glyph->bitmap;
++ /* Compensate for wrap around bug with negative minx's */
++ if ( (ch == text) && (glyph->minx < 0) ) {
++ xstart -= glyph->minx;
++ }
++
++ for( row = 0; row < current->rows; ++row ) {
++ /* Make sure we don't go over the limit */
++ if ( row+glyph->yoffset >= textbuf->h ) {
++ continue;
++ }
++ dst = (Uint8*) textbuf->pixels +
++ (row+glyph->yoffset) * textbuf->pitch +
++ xstart + glyph->minx;
++ src = current->buffer + row * current->pitch;
++
++ for ( col=current->width; col>0; --col ) {
++ *dst++ |= *src++;
++ }
++ }
++
++ xstart += glyph->advance;
++ if ( font->style & TTF_STYLE_BOLD ) {
++ xstart += font->glyph_overhang;
++ }
++ }
++
++ /* 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;
++ }
++ }
++ return textbuf;
++}
++
++SDL_Surface *TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ SDL_Palette *palette;
++ Uint8 *src, *dst;
++ int row;
++ FT_Error error;
++ c_glyph *glyph;
++
++ /* Get the glyph itself */
++ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_BITMAP);
++ if ( error ) {
++ return(NULL);
++ }
++ glyph = font->current;
++
++ /* Create the target surface */
++ textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE,
++ glyph->bitmap.pitch,
++ glyph->bitmap.rows,
++ 8, 0, 0, 0, 0 );
++ if ( ! textbuf ) {
++ return(NULL);
++ }
++
++ /* Fill the palette with the foreground color */
++ palette = textbuf->format->palette;
++ palette->colors[0].r = 255-fg.r;
++ palette->colors[0].g = 255-fg.g;
++ palette->colors[0].b = 255-fg.b;
++ palette->colors[1].r = fg.r;
++ palette->colors[1].g = fg.g;
++ palette->colors[1].b = fg.b;
++ SDL_SetColorKey(textbuf, SDL_SRCCOLORKEY, 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 );
++ 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;
++ }
++ }
++ return(textbuf);
++}
++
++
++/* Convert the Latin-1 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderText_Shaded(TTF_Font *font,
++ const char *text, SDL_Color fg, SDL_Color bg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the Latin-1 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++/* Convert the UTF-8 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderUTF8_Shaded(TTF_Font *font,
++ const char *text, SDL_Color fg, SDL_Color bg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the UTF-8 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++SDL_Surface* TTF_RenderUNICODE_Shaded( TTF_Font* font,
++ const Uint16* text,
++ SDL_Color fg,
++ SDL_Color bg )
++{
++ int xstart;
++ int width;
++ int height;
++ SDL_Surface* textbuf;
++ SDL_Palette* palette;
++ int index;
++ int rdiff;
++ int gdiff;
++ int bdiff;
++ const Uint16* ch;
++ Uint8* src;
++ Uint8* dst;
++ int swapped;
++ int row, col;
++ FT_Bitmap* current;
++ c_glyph *glyph;
++ FT_Error error;
++
++ /* Get the dimensions of the text surface */
++ if( ( TTF_SizeUNICODE(font, text, &width, NULL) < 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);
++ if( textbuf == NULL ) {
++ return NULL;
++ }
++
++ /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
++ palette = textbuf->format->palette;
++ rdiff = fg.r - bg.r;
++ gdiff = fg.g - bg.g;
++ bdiff = fg.b - bg.b;
++
++ for( index = 0; index < NUM_GRAYS; ++index ) {
++ palette->colors[index].r = bg.r + (index*rdiff) / (NUM_GRAYS-1);
++ palette->colors[index].g = bg.g + (index*gdiff) / (NUM_GRAYS-1);
++ palette->colors[index].b = bg.b + (index*bdiff) / (NUM_GRAYS-1);
++ }
++
++ /* Load and render each character */
++ xstart = 0;
++ swapped = TTF_byteswapped;
++ for( ch = text; *ch; ++ch ) {
++ Uint16 c = *ch;
++ if ( c == UNICODE_BOM_NATIVE ) {
++ swapped = 0;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( c == UNICODE_BOM_SWAPPED ) {
++ swapped = 1;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( swapped ) {
++ c = SDL_Swap16(c);
++ }
++
++ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
++ if( error ) {
++ SDL_FreeSurface( textbuf );
++ return NULL;
++ }
++ glyph = font->current;
++ /* Compensate for the wrap around with negative minx's */
++ if ( (ch == text) && (glyph->minx < 0) ) {
++ xstart -= glyph->minx;
++ }
++
++ current = &glyph->pixmap;
++ for( row = 0; row < current->rows; ++row ) {
++ /* Make sure we don't go over the limit */
++ if ( row+glyph->yoffset >= textbuf->h ) {
++ continue;
++ }
++ dst = (Uint8*) textbuf->pixels +
++ (row+glyph->yoffset) * textbuf->pitch +
++ xstart + glyph->minx;
++ src = current->buffer + row * current->pitch;
++ for ( col=current->width; col>0; --col ) {
++ *dst++ |= *src++;
++ }
++ }
++
++ xstart += glyph->advance;
++ if( font->style & TTF_STYLE_BOLD ) {
++ xstart += font->glyph_overhang;
++ }
++ }
++
++ /* 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;
++ }
++ }
++ return textbuf;
++}
++
++SDL_Surface* TTF_RenderGlyph_Shaded( TTF_Font* font,
++ Uint16 ch,
++ SDL_Color fg,
++ SDL_Color bg )
++{
++ SDL_Surface* textbuf;
++ SDL_Palette* palette;
++ int index;
++ int rdiff;
++ int gdiff;
++ int bdiff;
++ Uint8* src;
++ Uint8* dst;
++ int row;
++ FT_Error error;
++ c_glyph* glyph;
++
++ /* Get the glyph itself */
++ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP);
++ if( error ) {
++ return NULL;
++ }
++ glyph = font->current;
++
++ /* Create the target surface */
++ textbuf = SDL_CreateRGBSurface( SDL_SWSURFACE,
++ glyph->pixmap.width,
++ glyph->pixmap.rows,
++ 8, 0, 0, 0, 0 );
++ if( !textbuf ) {
++ return NULL;
++ }
++
++ /* Fill the palette with NUM_GRAYS levels of shading from bg to fg */
++ palette = textbuf->format->palette;
++ rdiff = fg.r - bg.r;
++ gdiff = fg.g - bg.g;
++ bdiff = fg.b - bg.b;
++ for( index = 0; index < NUM_GRAYS; ++index ) {
++ palette->colors[index].r = bg.r + (index*rdiff) / (NUM_GRAYS-1);
++ palette->colors[index].g = bg.g + (index*gdiff) / (NUM_GRAYS-1);
++ palette->colors[index].b = bg.b + (index*bdiff) / (NUM_GRAYS-1);
++ }
++
++ /* 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 );
++ 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;
++ }
++ }
++ return textbuf;
++}
++
++/* Convert the Latin-1 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderText_Blended(TTF_Font *font,
++ const char *text, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the Latin-1 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ LATIN1_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++/* Convert the UTF-8 text to UNICODE and render it
++*/
++SDL_Surface *TTF_RenderUTF8_Blended(TTF_Font *font,
++ const char *text, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ Uint16 *unicode_text;
++ int unicode_len;
++
++ /* Copy the UTF-8 text to a UNICODE text buffer */
++ unicode_len = strlen(text);
++ unicode_text = (Uint16 *)ALLOCA((1+unicode_len+1)*(sizeof *unicode_text));
++ if ( unicode_text == NULL ) {
++ TTF_SetError("Out of memory");
++ return(NULL);
++ }
++ *unicode_text = UNICODE_BOM_NATIVE;
++ UTF8_to_UNICODE(unicode_text+1, text, unicode_len);
++
++ /* Render the new text */
++ textbuf = TTF_RenderUNICODE_Blended(font, unicode_text, fg);
++
++ /* Free the text buffer and return */
++ FREEA(unicode_text);
++ return(textbuf);
++}
++
++SDL_Surface *TTF_RenderUNICODE_Blended(TTF_Font *font,
++ const Uint16 *text, SDL_Color fg)
++{
++ int xstart;
++ int width, height;
++ SDL_Surface *textbuf;
++ Uint32 alpha;
++ Uint32 pixel;
++ const Uint16 *ch;
++ Uint8 *src;
++ Uint32 *dst;
++ int swapped;
++ int row, col;
++ c_glyph *glyph;
++ FT_Error error;
++
++ /* Get the dimensions of the text surface */
++ if ( (TTF_SizeUNICODE(font, text, &width, NULL) < 0) || !width ) {
++ TTF_SetError("Text has zero width");
++ return(NULL);
++ }
++ height = font->height;
++
++ textbuf = SDL_AllocSurface(SDL_SWSURFACE, width, height, 32,
++ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
++ if ( textbuf == NULL ) {
++ return(NULL);
++ }
++
++ /* Load and render each character */
++ xstart = 0;
++ swapped = TTF_byteswapped;
++ pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
++ for ( ch=text; *ch; ++ch ) {
++ Uint16 c = *ch;
++ if ( c == UNICODE_BOM_NATIVE ) {
++ swapped = 0;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( c == UNICODE_BOM_SWAPPED ) {
++ swapped = 1;
++ if ( text == ch ) {
++ ++text;
++ }
++ continue;
++ }
++ if ( swapped ) {
++ c = SDL_Swap16(c);
++ }
++ error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
++ if( error ) {
++ SDL_FreeSurface( textbuf );
++ return NULL;
++ }
++ glyph = font->current;
++ width = glyph->pixmap.width;
++ /* Compensate for the wrap around bug with negative minx's */
++ if ( (ch == text) && (glyph->minx < 0) ) {
++ xstart -= glyph->minx;
++ }
++
++ for ( row = 0; row < glyph->pixmap.rows; ++row ) {
++ /* Make sure we don't go over the limit */
++ if ( row+glyph->yoffset >= textbuf->h ) {
++ continue;
++ }
++ dst = (Uint32*) textbuf->pixels +
++ (row+glyph->yoffset) * textbuf->pitch/4 +
++ xstart + glyph->minx;
++ /* Added code to adjust src pointer for pixmaps to
++ * account for pitch.
++ * */
++ src = (Uint8*) (glyph->pixmap.buffer + glyph->pixmap.pitch * row);
++ for ( col = width; col>0; --col) {
++ alpha = *src++;
++ *dst++ |= pixel | (alpha << 24);
++ }
++ }
++
++ xstart += glyph->advance;
++ if ( font->style & TTF_STYLE_BOLD ) {
++ xstart += font->glyph_overhang;
++ }
++ }
++
++ /* 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;
++ }
++ }
++ return(textbuf);
++}
++
++SDL_Surface *TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg)
++{
++ SDL_Surface *textbuf;
++ Uint32 alpha;
++ Uint32 pixel;
++ Uint8 *src;
++ Uint32 *dst;
++ int row, col;
++ FT_Error error;
++ c_glyph *glyph;
++
++ /* Get the glyph itself */
++ error = Find_Glyph(font, ch, CACHED_METRICS|CACHED_PIXMAP);
++ if ( error ) {
++ return(NULL);
++ }
++ glyph = font->current;
++
++ textbuf = SDL_CreateRGBSurface(SDL_SWSURFACE,
++ glyph->pixmap.width, glyph->pixmap.rows, 32,
++ 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
++ if ( ! textbuf ) {
++ return(NULL);
++ }
++
++ /* Copy the character from the pixmap */
++ pixel = (fg.r<<16)|(fg.g<<8)|fg.b;
++ for ( row=0; row<textbuf->h; ++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;
++ for ( col=0; col<glyph->pixmap.width; ++col ) {
++ alpha = *src++;
++ *dst++ = pixel | (alpha << 24);
++ }
++ }
++
++ /* 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;
++ }
++ }
++ return(textbuf);
++}
++
++void TTF_SetFontStyle( TTF_Font* font, int style )
++{
++ font->style = style;
++ Flush_Cache( font );
++}
++
++int TTF_GetFontStyle( TTF_Font* font )
++{
++ return font->style;
++}
++
++void TTF_Quit( void )
++{
++ if ( TTF_initialized ) {
++ if ( --TTF_initialized == 0 ) {
++ FT_Done_FreeType( library );
++ }
++ }
++}
++
++int TTF_WasInit( void )
++{
++ return TTF_initialized;
++}