📄 freetype.c
字号:
/*** $Id: freetype.c,v 1.26 2003/09/25 04:08:54 snig Exp $** ** freetype.c: TrueType font support based on FreeType 1.3.1.** ** Copyright (C) 2003 Feynman Software.** Copyright (C) 2000 ~ 2002 Wei Yongming.**** Current maintainer: WEI Yongming.**** Create date: 2000/08/21*//*** 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** Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,** MA 02111-1307, USA*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <math.h>#include "common.h"#include "minigui.h"#include "gdi.h"#include "devfont.h"#include "charset.h"#include "fontname.h"#include "misc.h"#if defined(_TTF_SUPPORT) && !defined(_HAS_FREETYPE2)#include <freetype1/freetype/freetype.h>#include <freetype1/freetype/ftxkern.h>#include <freetype1/freetype/ftnameid.h>#include <freetype1/freetype/ftxcmap.h>#include <freetype1/freetype/ftxwidth.h>#include "freetype.h"#if TT_FREETYPE_MAJOR != 1 | TT_FREETYPE_MINOR < 3 #error "You must link with freetype lib version 1.3.x +, and not freetype 2. \ You can download it at http://www.freetype.org"#endif/******************************* Global data ********************************/static TT_Engine ttf_engine; /* The ONLY freetype engine */static BYTE virtual_palette [] = {0, 32, 64, 128, 255};/************************ Create/Destroy FreeType font ***********************/static BOOL CreateFreeTypeFont (const char *name, TTFGLYPHINFO* ttf_glyph_info){ unsigned short i, n; unsigned short platform, encoding; TT_Face_Properties properties; /* Load face */ if (TT_Open_Face (ttf_engine, name, &ttf_glyph_info->face) != TT_Err_Ok) return FALSE; /* Load first kerning table */ ttf_glyph_info->can_kern = TRUE; if (TT_Load_Kerning_Table (ttf_glyph_info->face, 0) != TT_Err_Ok) ttf_glyph_info->can_kern = FALSE; else { if (TT_Get_Kerning_Directory (ttf_glyph_info->face, &ttf_glyph_info->directory) != TT_Err_Ok) ttf_glyph_info->can_kern = FALSE; else { /* Support only version 0 kerning table ... */ if ((ttf_glyph_info->directory.version != 0) || (ttf_glyph_info->directory.nTables <= 0) || (ttf_glyph_info->directory.tables->loaded != 1) || (ttf_glyph_info->directory.tables->version != 0) || (ttf_glyph_info->directory.tables->t.kern0.nPairs <= 0)) ttf_glyph_info->can_kern = FALSE; } }#if 0 fprintf (stderr, "Font %s: can kern? %c\n", name, ttf_glyph_info->can_kern ? 'y' : 'n');#endif /* Get face properties and allocate preload arrays */ TT_Get_Face_Properties (ttf_glyph_info->face, &properties); /* Create a glyph container */ if (TT_New_Glyph (ttf_glyph_info->face, &ttf_glyph_info->glyph) != TT_Err_Ok) return FALSE; /* Look for a Unicode charmap: Windows flavor of Apple flavor only */ n = properties.num_CharMaps; for (i = 0; i < n; i++) { TT_Get_CharMap_ID (ttf_glyph_info->face, i, &platform, &encoding); if (((platform == TT_PLATFORM_MICROSOFT) && (encoding == TT_MS_ID_UNICODE_CS)) || ((platform == TT_PLATFORM_APPLE_UNICODE) && (encoding == TT_APPLE_ID_DEFAULT))) { TT_Get_CharMap (ttf_glyph_info->face, i, &ttf_glyph_info->char_map); i = n + 1; } } if (i == n) { fprintf (stderr, "GDI (When Create TTF Font): no unicode map table\n"); return FALSE; } ttf_glyph_info->first_char = TT_CharMap_First (ttf_glyph_info->char_map, NULL); ttf_glyph_info->last_char = TT_CharMap_Last (ttf_glyph_info->char_map, NULL); ttf_glyph_info->last_glyph_index = (properties.num_Glyphs > 255) ? 255 : properties.num_Glyphs - 1; return TRUE;}static void DestroyFreeTypeFont (TTFGLYPHINFO* ttf_glyph_info){ if (ttf_glyph_info->valid) { TT_Done_Glyph (ttf_glyph_info->glyph); TT_Close_Face (ttf_glyph_info->face); ttf_glyph_info->valid = FALSE; }}/************************ Alloc/Free raster bitmap buffer ********************/static BYTE* rb_buffer;static size_t rb_buf_size;static BYTE* get_raster_bitmap_buffer (size_t size){ if (size <= rb_buf_size) return rb_buffer; rb_buf_size = ((size + 31) >> 5) << 5;#if 0 fprintf (stderr, "buf_size: %d.\n", buf_size);#endif rb_buffer = realloc (rb_buffer, rb_buf_size); return rb_buffer;}static void free_raster_bitmap_buffer (void){ free (rb_buffer); rb_buffer = NULL; rb_buf_size = 0;}/************************ Init/Term of FreeType fonts ************************/static int nr_fonts;static TTFGLYPHINFO* ttf_glyph_infos;static DEVFONT* ttf_dev_fonts;#define SECTION_NAME "truetypefonts"BOOL InitFreeTypeFonts (void){ int i; char font_name [LEN_UNIDEVFONT_NAME + 1]; /* Does load TrueType fonts? */ if (GetMgEtcIntValue (SECTION_NAME, "font_number", &nr_fonts) < 0 ) return FALSE; if ( nr_fonts < 1) return TRUE; /* Alloc space for devfont and ttfinfo. */ ttf_glyph_infos = calloc (nr_fonts, sizeof (TTFGLYPHINFO)); ttf_dev_fonts = calloc (nr_fonts, sizeof (DEVFONT)); if (ttf_glyph_infos == NULL || ttf_dev_fonts == NULL) { goto error_alloc; } for (i = 0; i < nr_fonts; i++) ttf_glyph_infos [i].valid = FALSE; /* Init freetype library */ if (TT_Init_FreeType (&ttf_engine) != TT_Err_Ok) { goto error_alloc; } TT_Set_Raster_Gray_Palette (ttf_engine, virtual_palette); /* Init kerning extension */ if (TT_Init_Kerning_Extension (ttf_engine) != TT_Err_Ok) { TT_Done_FreeType (ttf_engine); goto error_alloc; } for (i = 0; i < nr_fonts; i++) { char key [11]; char charset [LEN_FONT_NAME + 1]; char file [MAX_PATH + 1]; CHARSETOPS* charset_ops; sprintf (key, "name%d", i); if (GetMgEtcValue (SECTION_NAME, key, font_name, LEN_UNIDEVFONT_NAME) < 0 ) goto error_load; if (!fontGetCharsetFromName (font_name, charset)) { fprintf (stderr, "GDI: Invalid font name (charset): %s.\n", font_name); goto error_load; } if ((charset_ops = GetCharsetOps (charset)) == NULL) { fprintf (stderr, "GDI: Not supported charset: %s.\n", charset); goto error_load; } sprintf (key, "fontfile%d", i); if (GetMgEtcValue (SECTION_NAME, key, file, MAX_PATH) < 0) goto error_load; if (!CreateFreeTypeFont (file, ttf_glyph_infos + i)) goto error_load; strncpy (ttf_dev_fonts[i].name, font_name, LEN_UNIDEVFONT_NAME); ttf_dev_fonts[i].name [LEN_UNIDEVFONT_NAME] = '\0'; ttf_dev_fonts[i].font_ops = &freetype_font_ops; ttf_dev_fonts[i].charset_ops = charset_ops; ttf_dev_fonts[i].data = ttf_glyph_infos + i;#if 0 fprintf (stderr, "GDI: TTFDevFont %i: %s.\n", i, ttf_dev_fonts[i].name);#endif ttf_glyph_infos [i].valid = TRUE; } for (i = 0; i < nr_fonts; i++) { int nr_charsets; char charsets [LEN_UNIDEVFONT_NAME + 1]; if (ttf_dev_fonts [i].charset_ops->bytes_maxlen_char > 1) { AddMBDevFont (ttf_dev_fonts + i); } else AddSBDevFont (ttf_dev_fonts + i); fontGetCharsetPartFromName (ttf_dev_fonts[i].name, charsets); if ((nr_charsets = charsetGetCharsetsNumber (charsets)) > 1) { int j; for (j = 1; j < nr_charsets; j++) { char charset [LEN_FONT_NAME + 1]; CHARSETOPS* charset_ops; DEVFONT* new_devfont; charsetGetSpecificCharset (charsets, j, charset); if ((charset_ops = GetCharsetOps (charset)) == NULL) continue; new_devfont = calloc (1, sizeof (DEVFONT)); memcpy (new_devfont, ttf_dev_fonts + i, sizeof (DEVFONT)); new_devfont->charset_ops = charset_ops; if (new_devfont->charset_ops->bytes_maxlen_char > 1) AddMBDevFont (new_devfont); else AddSBDevFont (new_devfont); } } } return TRUE;error_load: fprintf (stderr, "GDI: Error in loading TrueType fonts\n"); for (i = 0; i < nr_fonts; i++) DestroyFreeTypeFont (ttf_glyph_infos + i);error_alloc: free (ttf_glyph_infos); free (ttf_dev_fonts); ttf_glyph_infos = NULL; ttf_dev_fonts = NULL; TT_Done_FreeType (ttf_engine); return FALSE;}void TermFreeTypeFonts (void){ if (ttf_glyph_infos) { TT_Done_FreeType (ttf_engine); ttf_glyph_infos = NULL; } free_raster_bitmap_buffer ();}/*************** TrueType on FreeType font operations ************************/static TT_UShort Get_Glyph_Width (TTFINSTANCEINFO* ttf_inst_info, TT_UShort glyph_index){ TT_F26Dot6 xmin, xmax; TT_Outline outline; TT_BBox bbox; TTFGLYPHINFO* ttf_glyph_info = ttf_inst_info->ttf_glyph_info; if (TT_Load_Glyph (ttf_inst_info->instance, ttf_glyph_info->glyph, glyph_index, TTLOAD_DEFAULT) != TT_Err_Ok) { /* Try to load default glyph: index 0 */ if (TT_Load_Glyph (ttf_inst_info->instance, ttf_glyph_info->glyph, 0, TTLOAD_DEFAULT) != TT_Err_Ok) { return 0; } } TT_Get_Glyph_Outline (ttf_glyph_info->glyph, &outline); TT_Get_Outline_BBox (&outline, &bbox); xmin = (bbox.xMin & -64) >> 6; xmax = ((bbox.xMax + 63) & -64) >> 6; return (xmax - xmin);}static int get_char_width (LOGFONT* logfont, DEVFONT* devfont, const unsigned char* mchar, int len){ TT_UShort index; TTFINSTANCEINFO* ttf_inst_info = TTF_INST_INFO_P (devfont); index = TT_Char_Index (ttf_inst_info->ttf_glyph_info->char_map, (*devfont->charset_ops->conv_to_uc16) (mchar, len)); if (index < 256) return ttf_inst_info->widths [index]; return ttf_inst_info->ave_width;}static int get_max_width (LOGFONT* logfont, DEVFONT* devfont){ TTFINSTANCEINFO* ttf_inst_info = TTF_INST_INFO_P (devfont); return ttf_inst_info->max_width;}static intcompute_kernval (TTFINSTANCEINFO* ttf_inst_info){ int i = 0; int kernval; TTFGLYPHINFO* ttf_glyph_info = ttf_inst_info->ttf_glyph_info; int nPairs = ttf_glyph_info->directory.tables->t.kern0.nPairs; TT_Kern_0_Pair *pair = ttf_glyph_info->directory.tables->t.kern0.pairs; if (ttf_inst_info->last_glyph_code != -1) { while ((pair->left != ttf_inst_info->last_glyph_code) && (pair->right != ttf_inst_info->cur_glyph_code)) { pair++; i++; if (i == nPairs) break; } if (i == nPairs) kernval = 0; else /* We round the value (hence the +32) */ kernval = (pair->value + 32) & -64; } else kernval = 0; return kernval;}static int get_str_width (LOGFONT* logfont, DEVFONT* devfont, const unsigned char* mstr, int n, int cExtra){ unsigned short uni_char; TT_F26Dot6 x = 0; TT_UShort index; TTFINSTANCEINFO* ttf_inst_info = TTF_INST_INFO_P (devfont); TTFGLYPHINFO* ttf_glyph_info = ttf_inst_info->ttf_glyph_info;#if 1 TT_Glyph_Metrics metrics;#endif ttf_inst_info->last_glyph_code = -1; /* reset kerning*/ ttf_inst_info->last_pen_pos = -1; while (n > 0) { int char_len = (*devfont->charset_ops->len_first_char) (mstr, n); uni_char = (*devfont->charset_ops->conv_to_uc16) (mstr, char_len); n -= char_len; mstr += char_len; index = TT_Char_Index (ttf_glyph_info->char_map, uni_char); if (index < 256) x += ttf_inst_info->widths [index]; else {#if 1 if (TT_Load_Glyph (ttf_inst_info->instance, ttf_glyph_info->glyph, index, TTLOAD_DEFAULT) != TT_Err_Ok) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -