?? ttf.c
字號:
/* render true type fonts to fb0 * * (w) by stepan@suse.de, code reused from SDL_ttf * */#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <freetype/freetype.h>#include <freetype/ftoutln.h>#include <freetype/ttnameid.h>#include "ttf.h"#define DEFAULT_PTSIZE 18/* 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 256extern unsigned int fbbytes, fbx, fby, fblinelen, alpha;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);/* 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;} 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;};static void Flush_Glyph(c_glyph * glyph);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); }}/* character conversion *//* Macro to convert a character to a Unicode value -- assume already Unicode */#define UNICODE(c) cstatic 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;}#if 0static 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;}#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;}void TTF_Quit(void){ if (TTF_initialized) { FT_Done_FreeType(library); } TTF_initialized = 0;}#if 0SDL_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); 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);}#endifunsigned 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);}void TTF_CloseFont(TTF_Font * font){ Flush_Cache(font); FT_Done_Face(font->face); free(font);}void TTF_SetFontStyle(TTF_Font * font, int style){ font->style = style; Flush_Cache(font);}TTF_Font *TTF_OpenFontIndex(const char *file, int ptsize, long index){ 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; }#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_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 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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -