aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fbtruetype/ttf.c1290
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;
}
+