diff options
-rw-r--r-- | fbtruetype/ttf.c | 1290 |
1 files changed, 629 insertions, 661 deletions
diff --git a/fbtruetype/ttf.c b/fbtruetype/ttf.c index 4e16f17..c102608 100644 --- a/fbtruetype/ttf.c +++ b/fbtruetype/ttf.c @@ -12,6 +12,9 @@ #include <ft2build.h> #include FT_FREETYPE_H +#include <freetype/freetype.h> +#include <freetype/ftoutln.h> +#include <freetype/ttnameid.h> #include "ttf.h" @@ -29,70 +32,69 @@ extern unsigned char *framebuffer; extern unsigned int fbypos, fbxpos; -unsigned char *TTF_RenderUNICODE_Shaded(TTF_Font * font, - const unsigned short *text, - unsigned int fg, unsigned int bg); +unsigned char* TTF_RenderUNICODE_Shaded( TTF_Font* font, + const unsigned short * text, unsigned int fg, unsigned int bg); /* 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; - unsigned short cached; + int stored; + FT_UInt index; + FT_Bitmap bitmap; + FT_Bitmap pixmap; + int minx; + int maxx; + int miny; + int maxy; + int yoffset; + int advance; + unsigned short cached; } c_glyph; 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; + /* 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; }; -static void Flush_Glyph(c_glyph * glyph); +static void Flush_Glyph( c_glyph* glyph ); -static void Flush_Cache(TTF_Font * font) +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); - } - -} + 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 ); + } + +} /* character conversion */ @@ -102,461 +104,438 @@ static void Flush_Cache(TTF_Font * font) -static unsigned short *ASCII_to_UNICODE(unsigned short *unicode, - const char *text, int len) +static unsigned short *ASCII_to_UNICODE(unsigned short *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; + int i; + + for ( i=0; i < len; ++i ) { + unicode[i] = ((const unsigned char *)text)[i]; + } + unicode[i] = 0; + + return unicode; } - -#if 0 -static unsigned short *UTF8_to_UNICODE(unsigned short *unicode, - const char *utf8, int len) + +static unsigned short *UTF8_to_UNICODE(unsigned short *unicode, const char *utf8, int len) { - int i, j; - unsigned short ch; - - for (i = 0, j = 0; i < len; ++i, ++j) { - ch = ((const unsigned char *) utf8)[i]; - if (ch >= 0xF0) { - ch = (unsigned short) (utf8[i] & 0x07) << 18; - ch |= (unsigned short) (utf8[++i] & 0x3F) << 12; - ch |= (unsigned short) (utf8[++i] & 0x3F) << 6; - ch |= (unsigned short) (utf8[++i] & 0x3F); - } else if (ch >= 0xE0) { - ch = (unsigned short) (utf8[i] & 0x3F) << 12; - ch |= (unsigned short) (utf8[++i] & 0x3F) << 6; - ch |= (unsigned short) (utf8[++i] & 0x3F); - } else if (ch >= 0xC0) { - ch = (unsigned short) (utf8[i] & 0x3F) << 6; - ch |= (unsigned short) (utf8[++i] & 0x3F); - } - unicode[j] = ch; - } - unicode[j] = 0; - - return unicode; + int i, j; + unsigned short ch; + + for ( i=0, j=0; i < len; ++i, ++j ) { + ch = ((const unsigned char *)utf8)[i]; + if ( ch >= 0xF0 ) { + ch = (unsigned short)(utf8[i]&0x07) << 18; + ch |= (unsigned short)(utf8[++i]&0x3F) << 12; + ch |= (unsigned short)(utf8[++i]&0x3F) << 6; + ch |= (unsigned short)(utf8[++i]&0x3F); + } else + if ( ch >= 0xE0 ) { + ch = (unsigned short)(utf8[i]&0x3F) << 12; + ch |= (unsigned short)(utf8[++i]&0x3F) << 6; + ch |= (unsigned short)(utf8[++i]&0x3F); + } else + if ( ch >= 0xC0 ) { + ch = (unsigned short)(utf8[i]&0x3F) << 6; + ch |= (unsigned short)(utf8[++i]&0x3F); + } + unicode[j] = ch; + } + unicode[j] = 0; + + return unicode; } -#endif /* TTF stuff */ static FT_Library library; static int TTF_initialized = 0; -int TTF_Init(void) -{ - int status; - FT_Error error; - - status = 0; - error = FT_Init_FreeType(&library); - if (error) { - fprintf(stderr, "Couldn't init FreeType engine %d\n", - error); - status = -1; - } else { - TTF_initialized = 1; - } - return status; +int TTF_Init( void ) +{ + int status; + FT_Error error; + + status = 0; + error = FT_Init_FreeType( &library ); + if ( error ) { + fprintf(stderr, "Couldn't init FreeType engine %d\n", error ); + status = -1; + } else { + TTF_initialized = 1; + } + return status; } -void TTF_Quit(void) +void TTF_Quit( void ) { - if (TTF_initialized) { - FT_Done_FreeType(library); - } - TTF_initialized = 0; + if ( TTF_initialized ) { + FT_Done_FreeType( library ); + } + TTF_initialized = 0; } #if 0 -SDL_Surface *TTF_RenderText_Solid(TTF_Font * font, - const char *text, SDL_Color fg) +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 *) malloc((unicode_len + 1) * (sizeof *unicode_text)); - if (unicode_text == NULL) { - TTF_SetError("Out of memory"); - return (NULL); - } - ASCII_to_UNICODE(unicode_text, text, unicode_len); + 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 *)malloc((unicode_len+1)*(sizeof *unicode_text)); + if ( unicode_text == NULL ) { + TTF_SetError("Out of memory"); + return(NULL); + } + UTF8_to_UNICODE(unicode_text, text, unicode_len); RenderUnicode(font, unicode_text, fg); - - /* Render the new text */ - textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg); - - /* Free the text buffer and return */ - free(unicode_text); - return (textbuf); + + /* Render the new text */ + textbuf = TTF_RenderUNICODE_Solid(font, unicode_text, fg); + + /* Free the text buffer and return */ + free(unicode_text); + return(textbuf); } #endif -unsigned char *TTF_RenderText_Shaded(TTF_Font * font, const char *text, - unsigned int fg, unsigned int bg) +unsigned char*TTF_RenderText_Shaded(TTF_Font *font, const char *text, unsigned int fg, unsigned int bg) { - unsigned char *textbuf; - unsigned short *unicode_text; - int unicode_len; - - /* Copy the Latin-1 text to a UNICODE text buffer */ - unicode_len = strlen(text); - unicode_text = - (unsigned short *) malloc((unicode_len + 1) * - (sizeof *unicode_text)); - if (unicode_text == NULL) { - printf("Out of memory\n"); - return (NULL); - } - ASCII_to_UNICODE(unicode_text, text, unicode_len); - - /* Render the new text */ - textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg); - - /* Free the text buffer and return */ - free(unicode_text); - return (textbuf); + unsigned char *textbuf; + unsigned short *unicode_text; + int unicode_len; + + /* Copy the UTF-8 text to a UNICODE text buffer */ + unicode_len = strlen(text); + unicode_text = (unsigned short *)malloc((unicode_len+1)*(sizeof +*unicode_text)); + if ( unicode_text == NULL ) { + printf("Out of memory\n"); + return(NULL); + } + UTF8_to_UNICODE(unicode_text, text, unicode_len); + + /* Render the new text */ + textbuf = TTF_RenderUNICODE_Shaded(font, unicode_text, fg, bg); + + /* Free the text buffer and return */ + free(unicode_text); + return(textbuf); } -void TTF_CloseFont(TTF_Font * font) +void TTF_CloseFont( TTF_Font* font ) { - Flush_Cache(font); - FT_Done_Face(font->face); - free(font); -} + Flush_Cache( font ); + FT_Done_Face( font->face ); + free( font ); +} -void TTF_SetFontStyle(TTF_Font * font, int style) +void TTF_SetFontStyle( TTF_Font* font, int style ) { - font->style = style; - Flush_Cache(font); + font->style = style; + Flush_Cache( font ); } + - -TTF_Font *TTF_OpenFontIndex(const char *file, int ptsize, long index) +TTF_Font* TTF_OpenFontIndex( const char *file, int ptsize, long index ) { - TTF_Font *font; - FT_Error error; - FT_Face face; - FT_Fixed scale; + TTF_Font* font; + FT_Error error; + FT_Face face; + FT_Fixed scale; extern int strict_font; - font = (TTF_Font *) malloc(sizeof *font); - if (font == NULL) { - fprintf(stderr, "Out of memory\n"); - return NULL; - } - memset(font, 0, sizeof(*font)); - - /* Open the font and create ancillary data */ - error = FT_New_Face(library, file, 0, &font->face); - - if (error && !strict_font) - error = - FT_New_Memory_Face(library, - (const FT_Byte *) luxisri_ttf, - LUXISRI_SIZE, 0, &font->face); - - if (error) { - printf("Couldn't load font file\n"); - free(font); - return NULL; - } - - if (index != 0) { - if (font->face->num_faces > index) { - FT_Done_Face(font->face); - error = - FT_New_Face(library, file, index, &font->face); - if (error) { - printf("Couldn't get font face\n"); - free(font); - return NULL; - } - } else { - fprintf(stderr, "No such font face\n"); - free(font); - return NULL; - } - } - face = font->face; - - /* Make sure that our font face is scalable (global metrics) */ - if (!FT_IS_SCALABLE(face)) { - fprintf(stderr, "Font face is not scalable\n"); - TTF_CloseFont(font); - return NULL; - } - /* Set the character size and use default DPI (72) */ - error = FT_Set_Char_Size(font->face, 0, ptsize * 64, 0, 0); - if (error) { - fprintf(stderr, "Couldn't set font size\n"); - 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)); - if (font->underline_height < 1) { - font->underline_height = 1; - } + font = (TTF_Font*) malloc(sizeof *font); + if ( font == NULL ) { + fprintf(stderr, "Out of memory\n" ); + return NULL; + } + memset( font, 0, sizeof( *font ) ); + + /* Open the font and create ancillary data */ + error = FT_New_Face( library, file, 0, &font->face ); + + if( error && !strict_font ) + error=FT_New_Memory_Face(library, (const FT_Byte*)luxisri_ttf, LUXISRI_SIZE, 0, &font->face ); + + if( error ) { + printf( "Couldn't load font file\n"); + free( font ); + return NULL; + } + + if ( index != 0 ) { + if ( font->face->num_faces > index ) { + FT_Done_Face( font->face ); + error = FT_New_Face( library, file, index, &font->face +); + if( error ) { + printf( "Couldn't get font face\n"); + free( font ); + return NULL; + } + } else { + fprintf(stderr, "No such font face\n"); + free( font ); + return NULL; + } + } + face = font->face; + + /* Make sure that our font face is scalable (global metrics) */ + if ( ! FT_IS_SCALABLE(face) ) { + fprintf(stderr,"Font face is not scalable\n"); + TTF_CloseFont( font ); + return NULL; + } + /* Set the character size and use default DPI (72) */ + error = FT_Set_Char_Size( font->face, 0, ptsize * 64, 0, 0 ); + if( error ) { + fprintf(stderr, "Couldn't set font size\n"); + 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)); + 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); + 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; + /* 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; + return font; } -TTF_Font *TTF_OpenFont(const char *file, int ptsize) +TTF_Font* TTF_OpenFont( const char *file, int ptsize ) { - return TTF_OpenFontIndex(file, ptsize, 0); + return TTF_OpenFontIndex(file, ptsize, 0); } -static void Flush_Glyph(c_glyph * glyph) +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; + 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 FT_Error Load_Glyph(TTF_Font * font, unsigned short ch, - c_glyph * cached, int want) +static FT_Error Load_Glyph( TTF_Font* font, unsigned short ch, c_glyph* cached, int want) { - FT_Face face; - FT_Error error; - FT_GlyphSlot glyph; - FT_Glyph_Metrics *metrics; - FT_Outline *outline; - - assert(font); - assert(font->face); - - 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)) { - /* 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); - - /* 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)); - if (mono) { - 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 { - 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; - unsigned char *pixmap; - - /* The pixmap is a little hard, we have to add and clamp */ - for (row = dst->rows - 1; row >= 0; --row) { - pixmap = - (unsigned char *) 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] = - (unsigned char) 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; + FT_Face face; + FT_Error error; + FT_GlyphSlot glyph; + FT_Glyph_Metrics* metrics; + FT_Outline* outline; + + assert( font ); + assert( font->face ); + + 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) ) { + /* 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); + + /* 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 ) ); + if ( mono ) { + 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 { + 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; + unsigned char* pixmap; + + /* The pixmap is a little hard, we have to add and clamp */ + for( row = dst->rows - 1; row >= 0; --row ) { + pixmap = (unsigned char*) 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] = (unsigned char) 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; } @@ -565,240 +544,229 @@ static FT_Error Load_Glyph(TTF_Font * font, unsigned short ch, -static FT_Error Find_Glyph(TTF_Font * font, unsigned short ch, int want) +static FT_Error Find_Glyph( TTF_Font* font, unsigned short 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; + 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; } -int TTF_SizeUNICODE(TTF_Font * font, const unsigned short *text, int *w, - int *h) +int TTF_SizeUNICODE(TTF_Font *font, const unsigned short *text, int *w, int *h) { - int status; - const unsigned short *ch; - int x, z; - int minx, maxx; - int miny, maxy; - c_glyph *glyph; - FT_Error error; - - /* Initialize everything to 0 */ - if (!TTF_initialized) { - return -1; - } - status = 0; - minx = maxx = 0; - miny = maxy = 0; - - /* Load each character and sum it's bounding box */ - x = 0; - for (ch = text; *ch; ++ch) { - error = Find_Glyph(font, *ch, CACHED_METRICS); - if (error) { - return -1; - } - glyph = font->current; - - 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) - *h = font->height; - - return status; + int status; + const unsigned short *ch; + int x, z; + int minx, maxx; + int miny, maxy; + c_glyph *glyph; + FT_Error error; + + /* Initialize everything to 0 */ + if ( ! TTF_initialized ) { + return -1; + } + status = 0; + minx = maxx = 0; + miny = maxy = 0; + + /* Load each character and sum it's bounding box */ + x= 0; + for ( ch=text; *ch; ++ch ) { + error = Find_Glyph(font, *ch, CACHED_METRICS); + if ( error ) { + return -1; + } + glyph = font->current; + + 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 ) + *h = font->height; + + return status; } -unsigned char *TTF_RenderUNICODE_Shaded(TTF_Font * font, - const unsigned short *text, - unsigned int fg, unsigned int bg) +unsigned char* TTF_RenderUNICODE_Shaded( TTF_Font* font, + const unsigned short * text, + unsigned int fg, + unsigned int bg ) { - int xstart; - int width; - int height; - unsigned char *textbuf; - int rdiff; - int gdiff; - int bdiff; + int xstart; + int width; + int height; + unsigned char* textbuf; + int rdiff; + int gdiff; + int bdiff; unsigned short val, bgc; - const unsigned short *ch; - unsigned char *src; - unsigned char *dst; - 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) { - fprintf(stderr, "Text has zero width\n"); - return NULL; - } - height = font->height; - - /* Create the target surface */ - textbuf = malloc(width * height * fbbytes); - - if (textbuf == NULL) { - return NULL; - } - - /* Load and render each character */ - xstart = 0; - for (ch = text; *ch; ++ch) { - FT_Bitmap *current; - - error = - Find_Glyph(font, *ch, CACHED_METRICS | CACHED_PIXMAP); - if (error) { + const unsigned short* ch; + unsigned char* src; + unsigned char* dst; + 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 ) { + fprintf(stderr,"Text has zero width\n"); + return NULL; + } + height = font->height; + + /* Create the target surface */ + textbuf=malloc(width*height*fbbytes); + + if( textbuf == NULL ) { + return NULL; + } + + /* Load and render each character */ + xstart = 0; + for( ch = text; *ch; ++ch ) { + FT_Bitmap* current; + + error = Find_Glyph(font, *ch, CACHED_METRICS|CACHED_PIXMAP); + if( error ) { free(textbuf); - return NULL; - } - glyph = font->current; - - current = &glyph->pixmap; - for (row = 0; row < current->rows; ++row) { - dst = (unsigned char *) framebuffer + - (fbypos + row + glyph->yoffset) * fblinelen + - (xstart + glyph->minx + fbxpos) * fbbytes; - src = current->buffer + row * current->pitch; - for (col = current->width; col > 0; --col) { - val = *src++; - bgc = *(unsigned short *) dst; - + return NULL; + } + glyph = font->current; + + current = &glyph->pixmap; + for( row = 0; row < current->rows; ++row ) { + dst = (unsigned char *) framebuffer + + (fbypos+row+glyph->yoffset) * fblinelen + + (xstart + glyph->minx+fbxpos)*fbbytes; + src = current->buffer + row * current->pitch; + for ( col=current->width; col>0; --col ) { + val=*src++; + bgc=*(unsigned short *)dst; + /* get color parts from real color */ - rdiff = (fg >> 16); - gdiff = ((fg >> 8) & 0xff); - bdiff = (fg & 0xff); + rdiff=(fg>>16); + gdiff=((fg>>8)&0xff); + bdiff=(fg&0xff); - val = alpha * val / 100; + val=alpha*val/100; /* dim color down to current pixel value */ - rdiff = rdiff * val / 0xff; - gdiff = gdiff * val / 0xff; - bdiff = bdiff * val / 0xff; + rdiff=rdiff*val/0xff; + gdiff=gdiff*val/0xff; + bdiff=bdiff*val/0xff; #if 1 /* do alpha transparency */ //rdiff=(rdiff*alpha/100); - rdiff += - ((bgc) >> 8 & 0xf8) * (0xff - - val) / 0xff; + rdiff+=((bgc)>>8&0xf8)*(0xff-val)/0xff; //gdiff=(gdiff*alpha/100); - gdiff += - ((bgc >> 3) & 0xfc) * (0xff - - val) / 0xff; - + gdiff+=((bgc>>3)&0xfc)*(0xff-val)/0xff; + //bdiff=(bdiff*alpha/100); - bdiff += - ((bgc << 3) & 0xf8) * (0xff - - val) / 0xff; + bdiff+=((bgc<<3)&0xf8)*(0xff-val)/0xff; #endif - - val = - ((rdiff & 0xf8) << 8) | ((gdiff & 0xfc) - << 3) | (bdiff - >> - 3); - //*dst++ = (val >>8); - *dst++ = val & 0xff; - *dst++ = (val >> 8); - } + + val=((rdiff&0xf8)<<8)|((gdiff&0xfc)<<3)|(bdiff>>3); + //*dst++ = (val >>8); + *dst++ = val&0xff; + *dst++ = (val >>8); + } //printf("\n"); - } - - 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 >= fby) { - row = (height - 1) - font->underline_height; - } - dst = (unsigned char *) textbuf + row * width * fbbytes; - for (row = font->underline_height; row > 0; --row) { - memset(dst, NUM_GRAYS - 1, width); - dst += width * fbbytes; - } - } - return textbuf; + } + + 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 >= fby) { + row = (height-1) - font->underline_height; + } + dst = (unsigned char *)textbuf + row * width*fbbytes; + for ( row=font->underline_height; row>0; --row ) { + memset( dst, NUM_GRAYS - 1, width ); + dst += width*fbbytes; + } + } + return textbuf; } -int rendertext(char *text, char *fontname, unsigned int ptsize, - unsigned int forecol) +int rendertext(char *text, char *fontname, unsigned int ptsize, unsigned int forecol) { - TTF_Font *font; - int renderstyle = 0; - - enum { - RENDER_LATIN1, - RENDER_UTF8, - RENDER_UNICODE - } rendertype; - - - /* Initialize the TTF library */ - if (TTF_Init() < 0) { - fprintf(stderr, "Couldn't initialize TTF.\n"); - return (2); - } - atexit(TTF_Quit); - - /* Open the font file with the requested point size */ - font = TTF_OpenFont(fontname, ptsize); - if (font == NULL) { - fprintf(stderr, "Couldn't load %d pt font from %s\n", - ptsize, fontname); - return (2); - } - - renderstyle = TTF_STYLE_NORMAL; + TTF_Font *font; + int renderstyle=0; + + enum { + RENDER_LATIN1, + RENDER_UTF8, + RENDER_UNICODE + } rendertype; + + + /* Initialize the TTF library */ + if ( TTF_Init() < 0 ) { + fprintf(stderr, "Couldn't initialize TTF.\n"); + return(2); + } + atexit(TTF_Quit); + + /* Open the font file with the requested point size */ + font = TTF_OpenFont(fontname, ptsize); + if ( font == NULL ) { + fprintf(stderr, "Couldn't load %d pt font from %s\n", + ptsize, fontname ); + return(2); + } + + renderstyle = TTF_STYLE_NORMAL; rendertype = RENDER_UTF8; - - TTF_SetFontStyle(font, renderstyle); + + TTF_SetFontStyle(font, renderstyle); text = TTF_RenderText_Shaded(font, text, forecol, 0); return 0; } + |