int main(int argc, char *argv[]) { int i, j, err, size, first=' ', last='~', bitmapOffset = 0, x, y, byte; char *fontName, c, *ptr; FT_Library library; FT_Face face; FT_Glyph glyph; FT_Bitmap *bitmap; FT_BitmapGlyphRec *g; GFXglyph *table; uint8_t bit; // Parse command line. Valid syntaxes are: // fontconvert [filename] [size] // fontconvert [filename] [size] [last char] // fontconvert [filename] [size] [first char] [last char] // Unless overridden, default first and last chars are // ' ' (space) and '~', respectively if(argc < 3) { fprintf(stderr, "Usage: %s fontfile size [first] [last]\n", argv[0]); return 1; } size = atoi(argv[2]); if(argc == 4) { last = atoi(argv[3]); } else if(argc == 5) { first = atoi(argv[3]); last = atoi(argv[4]); } if(last < first) { i = first; first = last; last = i; } ptr = strrchr(argv[1], '/'); // Find last slash in filename if(ptr) ptr++; // First character of filename (path stripped) else ptr = argv[1]; // No path; font in local dir. // Allocate space for font name and glyph table if((!(fontName = malloc(strlen(ptr) + 20))) || (!(table = (GFXglyph *)malloc((last - first + 1) * sizeof(GFXglyph))))) { fprintf(stderr, "Malloc error\n"); return 1; } // Derive font table names from filename. Period (filename // extension) is truncated and replaced with the font size & bits. strcpy(fontName, ptr); ptr = strrchr(fontName, '.'); // Find last period (file ext) if(!ptr) ptr = &fontName[strlen(fontName)]; // If none, append // Insert font size and 7/8 bit. fontName was alloc'd w/extra // space to allow this, we're not sprintfing into Forbidden Zone. sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7); // Space and punctuation chars in name replaced w/ underscores. for(i=0; (c=fontName[i]); i++) { if(isspace(c) || ispunct(c)) fontName[i] = '_'; } // Init FreeType lib, load font if((err = FT_Init_FreeType(&library))) { fprintf(stderr, "FreeType init error: %d", err); return err; } if((err = FT_New_Face(library, argv[1], 0, &face))) { fprintf(stderr, "Font load error: %d", err); FT_Done_FreeType(library); return err; } // << 6 because '26dot6' fixed-point format FT_Set_Char_Size(face, size << 6, 0, DPI, 0); // Currently all symbols from 'first' to 'last' are processed. // Fonts may contain WAY more glyphs than that, but this code // will need to handle encoding stuff to deal with extracting // the right symbols, and that's not done yet. // fprintf(stderr, "%ld glyphs\n", face->num_glyphs); printf("package Giza.Bitmap_Fonts.%s is\n\n", fontName); printf(" %sBitmaps : aliased constant Font_Bitmap := (\n ", fontName); // Process glyphs and output huge bitmap data array for(i=first, j=0; i<=last; i++, j++) { // MONO renderer provides clean image with perfect crop // (no wasted pixels) via bitmap struct. if((err = FT_Load_Char(face, i, FT_LOAD_TARGET_MONO))) { fprintf(stderr, "Error %d loading char '%c'\n", err, i); continue; } if((err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))) { fprintf(stderr, "Error %d rendering char '%c'\n", err, i); continue; } if((err = FT_Get_Glyph(face->glyph, &glyph))) { fprintf(stderr, "Error %d getting glyph '%c'\n", err, i); continue; } bitmap = &face->glyph->bitmap; g = (FT_BitmapGlyphRec *)glyph; // Minimal font and per-glyph information is stored to // reduce flash space requirements. Glyph bitmaps are // fully bit-packed; no per-scanline pad, though end of // each character may be padded to next byte boundary // when needed. 16-bit offset means 64K max for bitmaps, // code currently doesn't check for overflow. (Doesn't // check that size & offsets are within bounds either for // that matter...please convert fonts responsibly.) table[j].bitmapOffset = bitmapOffset; table[j].width = bitmap->width; table[j].height = bitmap->rows; table[j].xAdvance = face->glyph->advance.x >> 6; table[j].xOffset = g->left; table[j].yOffset = 1 - g->top; for(y=0; y < bitmap->rows; y++) { for(x=0;x < bitmap->width; x++) { byte = x / 8; bit = 0x80 >> (x & 7); enbit(bitmap->buffer[ y * bitmap->pitch + byte] & bit); } } // Pad end of char bitmap to next byte boundary if needed int n = (bitmap->width * bitmap->rows) & 7; if(n) { // Pixel count not an even multiple of 8? n = 8 - n; // # bits to next multiple while(n--) enbit(0); } bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8; FT_Done_Glyph(glyph); } printf(");\n\n"); // End bitmap array // Output glyph attributes table (one per character) printf(" %sGlyphs : aliased constant Glyph_Array := (\n", fontName); for(i=first, j=0; i<=last; i++, j++) { printf(" (%d, %d, %d, %d, %d, %d)", table[j].bitmapOffset, table[j].width, table[j].height, table[j].xAdvance, table[j].xOffset, table[j].yOffset); if(i < last) { printf(", -- 0x%02X", i); if((i >= ' ') && (i <= '~')) { printf(" '%c'", i); } putchar('\n'); } } printf("); -- 0x%02X", last); if((last >= ' ') && (last <= '~')) printf(" '%c'", last); printf("\n\n"); // Output font structure printf(" Font : Bitmap_Font :=\n"); printf(" (%sBitmaps'Access,\n", fontName); printf(" %sGlyphs'Access,\n", fontName); printf(" 16#%02X#,\n", first); printf(" 16#%02X#,\n", last); printf(" %ld);\n", face->size->metrics.height >> 6); printf("end Giza.Bitmap_Fonts.%s;\n", fontName); FT_Done_FreeType(library); return 0; }
void TTF_Init(void) { if (!TTF_initialized && FT_Init_FreeType(&library)) E_Exit("TTF: Couldn't init FreeType engine"); TTF_initialized = true; }
/* ------------------------------------------------------------------------- */ int main ( int argc, char *argv[] ) { FT_Library library; FT_Face face; FT_FaceRec props; FT_Error error = 0; FT_UInt names; FT_CharMap charmap; FX_Kern_0 *kstable; TT_OS2 *pOS2; TT_Postscript *ppost; ULONG rc; BOOL bDumpUCS = FALSE; BOOL bShowKST = FALSE; BOOL bShowOS2 = FALSE; BOOL bShowPS = FALSE; char szPID[10]; char szEID[32]; int i; char *buf; if ( argc < 2 ) { printf("FONTNAME - Show summary of OpenType font names and other optional information.\n"); printf("Syntax: FONTNAME <filename> [ options ]\n\n"); printf(" /D Dump Unicode and DBCS strings as hex values\n"); printf(" /K Show kerning summary (KERN format 0 only)\n"); printf(" /O Show OS/2 table\n"); printf(" /P Show POST table\n\n"); printf("NAME and CMAP table information is always shown.\n\n"); printf("\nNo font file specified.\n"); return 0; } for ( i = 2; i < argc; i++ ) { if ( strlen( argv[i] ) > 1 ) { CHAR cOption = 0; if ( argv[i][0] == '/' || argv[i][0] == '-') cOption = argv[i][1]; switch ( cOption ) { case 'd': case 'D': bDumpUCS = TRUE; break; case 'k': case 'K': bShowKST = TRUE; break; case 'o': case 'O': bShowOS2 = TRUE; break; case 'p': case 'P': bShowPS = TRUE; break; default : break; } } } if (( rc = UniCreateUconvObject( L"@endian=big", &uconv )) != ULS_SUCCESS ) { printf("Failed to create Unicode conversion object (rc=0x%X).\n"); printf("Unicode text values will not be shown.\n"); uconv = NULL; } error = FT_Init_FreeType( &library ); if ( error ) { printf("An error occurred during library initialization.\n"); return (int) error; } printf("FreeType 2 library initialized successfully.\n"); error = FT_New_Face( library, argv[1], 0, &face ); if ( error ) { if ( error == FT_Err_Unknown_File_Format ) printf("The file format is unsupported.\n"); else printf("The file \"%s\" could not be loaded.\n", argv[1]); goto done; } printf("Font %s read successfully.\n", face->family_name ); names = FT_Get_Sfnt_Name_Count( face ); if ( names ) { printf("Names table contains %d entries:\n", names ); for ( i = 0; i < names; i++ ) { FT_SfntName name; error = FT_Get_Sfnt_Name( face, i, &name ); if ( error ) continue; printf("%2d: Plat %d, Enc %d, Lang 0x%X, ID %2d ", i, name.platform_id, name.encoding_id, name.language_id, name.name_id ); if ( name.platform_id == 1 && name.encoding_id == 0 && name.string_len < 100 ) { printf(" \""); PrintNameString( name.string, name.string_len ); printf("\"\n"); } else if ( name.platform_id == 3 && name.encoding_id == 1 && uconv && name.string_len < 200 ) { printf(" (U)\""); if (bDumpUCS) DumpUnicodeString( name.string, name.string_len ); else PrintUnicodeString( name.string, name.string_len ); printf("\"\n"); } else if ( name.string_len < 200 && bDumpUCS ) { printf(" \""); DumpUnicodeString( name.string, name.string_len ); printf("\"\n"); } else printf(" [%d bytes]\n", name.string_len ); } } printf("\nINCLUDED CMAPS"); printf("\n--------------\n"); for ( i = 0; i < face->num_charmaps; i++ ) { charmap = face->charmaps[i]; switch ( charmap->platform_id ) { case 0: strcpy( szPID, "Unicode"); switch ( charmap->encoding_id ) { case 0: strcpy( szEID, "default"); break; case 1: strcpy( szEID, "1.1"); break; case 3: strcpy( szEID, "2+"); break; case 4: strcpy( szEID, "3.1+ UTF-32"); break; default: strcpy( szEID, "unknown"); break; } break; case 1: strcpy( szPID, "Macintosh"); switch ( charmap->encoding_id ) { case 0: strcpy( szEID, "Roman"); break; case 1: strcpy( szEID, "Japanese"); break; case 2: strcpy( szEID, "Chinese-T"); break; case 3: strcpy( szEID, "Korean"); break; case 8: strcpy( szEID, "symbols"); break; case 25: strcpy( szEID, "Chinese-S"); break; default: strcpy( szEID, "other language");break; } break; case 3: strcpy( szPID, "Windows"); switch ( charmap->encoding_id ) { case 0: strcpy( szEID, "symbols"); break; case 1: strcpy( szEID, "Unicode"); break; case 2: strcpy( szEID, "Shift-JIS (Japan)"); break; case 3: strcpy( szEID, "GB2312 (China)"); break; case 4: strcpy( szEID, "Big5 (Taiwan)"); break; case 5: strcpy( szEID, "Wansung (Korea)"); break; case 6: strcpy( szEID, "Johab (Korea)"); break; case 10: strcpy( szEID, "UCS-4"); break; default: strcpy( szEID, "unknown"); break; } break; default: strcpy( szPID, "unknown"); strcpy( szEID, "unknown"); break; } printf("Platform: %d (%s), Encoding: %d (%s)\n", charmap->platform_id, szPID, charmap->encoding_id, szEID ); } #if 0 error = FX_Flush_Stream( face ); if ( error ) { printf("Failed to close stream: 0x%X\n", error ); FT_Done_Face( face ); goto done; } error = FX_Activate_Stream( face ); if ( error ) { printf("Failed to reopen stream: 0x%X\n", error ); FT_Done_Face( face ); goto done; } #endif if ( bShowKST ) { printf("\nKERNING INFORMATION"); printf("\n-------------------\n"); error = FX_Get_Kerning_Pairs( face, &kstable ); switch ( error ) { case 0: printf("%u kerning pairs defined:\n", kstable->nPairs ); if ( kstable->nPairs ) { for ( i = 0; i < kstable->nPairs; i++ ) { printf(" %X / %X (%d)\n", kstable->pairs[i].left, kstable->pairs[i].right, kstable->pairs[i].value ); } } safe_free( kstable ); break; case FT_Err_Table_Missing: printf("No kerning table defined.\n"); break; case FX_Err_Invalid_Kerning_Table: printf("The kerning table is invalid.\n"); break; case FT_Err_Out_Of_Memory: printf("Memory allocation error.\n"); break; case FX_Err_Invalid_Kerning_Table_Format: printf("No supported kerning table format found.\n"); break; default: printf("An unknown error (0x%X) was encountered.\n", error ); break; } } if ( bShowOS2 ) { printf("\nOS/2 TABLE"); printf("\n----------\n"); pOS2 = (TT_OS2 *) FT_Get_Sfnt_Table( face, ft_sfnt_os2 ); if ( pOS2 ) { printf("version: %u\n", pOS2->version ); printf("xAvgCharWidth: %d\n", pOS2->xAvgCharWidth ); printf("usWeightClass: %u\n", pOS2->usWeightClass ); printf("usWidthClass: %u\n", pOS2->usWidthClass ); printf("fsType: 0x%X\n", pOS2->fsType ); printf("ySubscriptXSize: %d\n", pOS2->ySubscriptXSize ); printf("ySubscriptYSize: %d\n", pOS2->ySubscriptYSize ); printf("ySubscriptXOffset: %d\n", pOS2->ySubscriptXOffset ); printf("ySubscriptYOffset: %d\n", pOS2->ySubscriptYOffset ); printf("ySuperscriptXSize: %d\n", pOS2->ySuperscriptXSize ); printf("ySuperscriptYSize: %d\n", pOS2->ySuperscriptYSize ); printf("ySuperscriptXOffset: %d\n", pOS2->ySuperscriptXOffset ); printf("ySuperscriptYOffset: %d\n", pOS2->ySuperscriptYOffset ); printf("yStrikeoutSize: %d\n", pOS2->yStrikeoutSize ); printf("yStrikeoutPosition: %d\n", pOS2->yStrikeoutPosition ); printf("sFamilyClass: %d\n", pOS2->sFamilyClass ); printf("panose: []\n"); printf("ulUnicodeRange1: 0x%X\n", pOS2->ulUnicodeRange1 ); printf("ulUnicodeRange2: 0x%X\n", pOS2->ulUnicodeRange2 ); printf("ulUnicodeRange3: 0x%X\n", pOS2->ulUnicodeRange3 ); printf("ulUnicodeRange4: 0x%X\n", pOS2->ulUnicodeRange4 ); printf("achVendID: %c%c%c%c\n", pOS2->achVendID[0], pOS2->achVendID[1], pOS2->achVendID[2], pOS2->achVendID[3] ); printf("fsSelection: 0x%X\n", pOS2->fsSelection ); printf("usFirstCharIndex: %u\n", pOS2->usFirstCharIndex ); printf("usLastCharIndex: %u\n", pOS2->usLastCharIndex ); printf("sTypoAscender: %d\n", pOS2->sTypoAscender ); printf("sTypoDescender: %d\n", pOS2->sTypoDescender ); printf("sTypoLineGap: %d\n", pOS2->sTypoLineGap ); printf("usWinAscent: %u\n", pOS2->usWinAscent ); printf("usWinDescent: %u\n", pOS2->usWinDescent ); } else printf("OS/2 table could not be located.\n"); } if ( bShowPS) { printf("\nPOST TABLE"); printf("\n----------\n"); ppost = (TT_Postscript *) FT_Get_Sfnt_Table( face, ft_sfnt_post ); if ( ppost ) { printf("FormatType: 0x%X\n", ppost->FormatType ); printf("italicAngle: %d\n", ppost->italicAngle ); printf("underlinePosition: %d\n", ppost->underlinePosition ); printf("underlineThickness: %d\n", ppost->underlineThickness ); printf("isFixedPitch: %u\n", ppost->isFixedPitch ); printf("minMemType42: %u\n", ppost->minMemType42 ); printf("maxMemType42: %u\n", ppost->maxMemType42 ); printf("minMemType1: %u\n", ppost->minMemType1 ); printf("maxMemType1: %u\n", ppost->maxMemType1 ); } else printf("POST table could not be loaded.\n"); } error = FT_Done_Face( face ); done: FT_Done_FreeType( library ); if ( uconv ) UniFreeUconvObject( uconv ); return (int) error; }
FreetypeFontProvider::FreetypeFontProvider(const FontProvider::Options& options): FontProvider(options) { if ( options.size.height < 1 ) { throw std::runtime_error("[FreetypeFontProvider] Invalid size"); } if ( options.mode == L"" || options.mode == L"normal" ) { m_render_mode = FT_RENDER_MODE_NORMAL; } else if ( options.mode == L"monochrome" ) { m_render_mode = FT_RENDER_MODE_MONO; } else if ( options.mode == L"lcd" ) { m_render_mode = FT_RENDER_MODE_LCD; } else { throw std::runtime_error("[FreetypeFontProvider] Invalid font.mode"); } if ( FT_Init_FreeType(&m_font_library) ) { throw std::runtime_error("[FreetypeFontProvider] Can't initialize Freetype"); } std::string filename_u8 = Encoding::UTF8.FromUCS2(options.name); if ( FT_New_Face(m_font_library, filename_u8.c_str(), 0, &m_font_face) ) { Dispose(); throw std::runtime_error("[FreetypeFontProvider] Can't load font from file"); } int hres = 64; FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L), (int)((0.0) * 0x10000L), (int)((0.0) * 0x10000L), (int)((1.0) * 0x10000L) }; if ( FT_Set_Char_Size(m_font_face, (uint32_t)(options.size.height*64), 0, 96*hres, 96) ) { Dispose(); throw std::runtime_error("[FreetypeFontProvider] Can't setup font"); } FT_Set_Transform(m_font_face, &matrix, NULL); float yscale = m_font_face->size->metrics.y_scale / (float)(1 << 16); int height = std::ceil((m_font_face->bbox.yMax-m_font_face->bbox.yMin) * yscale / 64.0f); //int descender = std::floor(m_font_face->descender * yscale / 64.0f); //int ascender = std::ceil(m_font_face->ascender * yscale / 64.0f); auto get_metrics = [&](wchar_t code) -> FT_Glyph_Metrics { if ( FT_Load_Glyph(m_font_face, FT_Get_Char_Index(m_font_face, code), 0) ) { throw std::runtime_error("[FreetypeFontProvider] Metrics error"); } return m_font_face->glyph->metrics; }; int width = 0; FT_Glyph_Metrics mDot = get_metrics(L'.'), mAt = get_metrics(L'@'); if ( mDot.horiAdvance == mAt.horiAdvance ) { // Monospace font width = std::ceil(mDot.horiAdvance / 64.0f); } else { // This is not a monospace font //throw std::runtime_error("[FreetypeFontProvider::ctor] This is not a monospace font"); width = std::ceil(mAt.horiAdvance / 64.0f); } width = std::ceil(width/64.0); height = m_font_face->size->metrics.height >> 6; //descender = m_font_face->size->metrics.descender >> 6; m_cell_size = Size(width, height); m_glyph_size = Size(width, height); FT_Library_SetLcdFilter(m_font_library, FT_LCD_FILTER_DEFAULT); return; }
TTFLibrary::TTFLibrary() : _library(), _initialized(false) { if (!FT_Init_FreeType(&_library)) _initialized = true; }
Font::Font() { if(FT_Init_FreeType(&library)) throw love::Exception("TrueTypeFont Loading error: FT_Init_FreeType failed\n"); }
tgon::FTFontManager::FTFontManager( ) { FT_Init_FreeType( &library ); }
//******************** M A I N ************************ void get_font(string FontName_base, char letter, int ptsize, vect2d *times) { _mkdir("font_rasters"); std::string FontName = "fonts/" + FontName_base + ".ttf"; char buf[256]; string letter_name; letter_name += letter; if (letter >= 'A' && letter <= 'Z') letter_name += letter; //----------------------------------------- // Load contour of glyph //----------------------------------------- lines.clear(); bez2s.clear(); FT_Face face; FT_Library library; FT_Error error; error = FT_Init_FreeType( &library ); Check(error, "", "error initializing FT lib"); error = FT_New_Face( library, FontName.c_str(), 0, &face ); Check(error, "", "error loading font"); FT_F26Dot6 font_size = ptsize*64; error = FT_Set_Char_Size( face, font_size, font_size, 72, 72 ); Check(error, "", "error setting char size"); FT_UInt glyph_index = FT_Get_Char_Index( face, letter ); FT_Int32 load_flags = FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP; error = FT_Load_Glyph( face, glyph_index, load_flags ); Check(error, "", "error loading glyph"); FT_Glyph glyph; error = FT_Get_Glyph( face->glyph, &glyph ); Check(error, "", "error getting glyph"); FT_OutlineGlyph Outg; error = GetOutLine(glyph, &Outg); Check(error,"", "error getting outline"); // use my own callcacks to walk over the contour FT_Outline_Funcs func_interface; func_interface.shift = 0; func_interface.delta = 0; func_interface.move_to = move_to; func_interface.line_to = line_to; func_interface.conic_to = conic_to; func_interface.cubic_to = cubic_to; FT_Outline_Decompose(&Outg->outline, &func_interface, 0); //----------------------------------------- // Rasterize using FreeType //----------------------------------------- // rasterize using FreeType so that a comparison to my code can be made double t_ft_start = get_time(); FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); double t_ft_stop = get_time(); // save timing FILE *fa = fopen("timings.txt", "a"); fprintf(fa, "time FreeType = %f\n", t_ft_stop - t_ft_start); fclose(fa); // create grid / calculate resolution g.max_depth = 0; g.grid_res = 2; int maxsize = max(face->glyph->bitmap.width, face->glyph->bitmap.rows); while (g.grid_res < maxsize) { g.grid_res *= 2; g.max_depth++; } vect2i offset; offset.set((g.grid_res - face->glyph->bitmap.width) / 2, (g.grid_res - face->glyph->bitmap.rows) / 2); // copy bitmap into a buffer Array2D<vect3ub> ftgrid; ftgrid.resize(g.grid_res, g.grid_res); for (int k = 0; k < g.grid_res*g.grid_res; k++) ftgrid.data[k].set(0); for (int j = 0; j < face->glyph->bitmap.rows; j++) { unsigned char *row = face->glyph->bitmap.buffer + (face->glyph->bitmap.rows-j-1)*face->glyph->bitmap.pitch; for (int i = 0; i < face->glyph->bitmap.width; i++) { ftgrid(i + offset[0], j + offset[1]) = row[i]; } } sprintf(buf, "font_rasters/%s_%04d_%s_1_ft.png", FontName_base.c_str(), ptsize, letter_name.c_str()); save_png(buf, ftgrid); //----------------------------------------- // Rasterize using our method //----------------------------------------- // get bbox FT_BBox bbox; FT_Outline_Get_BBox(&Outg->outline, &bbox); //printf("bbox = (%f, %f), (%f, %f)\n", bbox.xMin/64., bbox.yMin/64., bbox.xMax/64., bbox.yMax/64.); // fit in box vect2f ext; ext.set(bbox.xMax/64. - bbox.xMin/64., bbox.yMax/64. - bbox.yMin/64.); float maxext = std::max(ext[0], ext[1]) * 1.1; for (int i = 0; i < lines.s; i++) { //printf("line\n"); for (int j = 0; j < 2; j++) { lines[i][j][0] = (lines[i][j][0] - floor(bbox.xMin/64.) + offset[0]) / g.grid_res; lines[i][j][1] = (lines[i][j][1] - floor(bbox.yMin/64.) + offset[1]) / g.grid_res; //printf("%f %f\n", lines[i][j][0], lines[i][j][1]); } } for (int i = 0; i < bez2s.s; i++) { //printf("bez2\n"); for (int j = 0; j < 3; j++) { bez2s[i][j][0] = (bez2s[i][j][0] - floor(bbox.xMin/64.) + offset[0]) / g.grid_res; bez2s[i][j][1] = (bez2s[i][j][1] - floor(bbox.yMin/64.) + offset[1]) / g.grid_res; //printf("%f %f\n", bez2s[i][j][0], bez2s[i][j][1]); } } //vect3ub *grid = new vect3ub [g.grid_res*g.grid_res]; Array2D<float> grid; Array2D<vect3ub> ourgrid; grid.resize(g.grid_res, g.grid_res); ourgrid.resize(g.grid_res, g.grid_res); // rasterize for (int k = 0; k < g.grid_res*g.grid_res; k++) grid.data[k] = 0; double t_ours_start = get_time(); raster_poly(lines, bez2s, grid.data); double t_ours_stop = get_time(); // save timing FILE *f = fopen("timings.txt", "a"); fprintf(f, "time wavelet = %f\n", (t_ours_stop - t_ours_start)); fclose(f); // copy into color image and save for (int k = 0; k < g.grid_res*g.grid_res; k++) { if (grid.data[k] >= 1) ourgrid.data[k] = 255; else if (grid.data[k] <= 0) ourgrid.data[k] = 0; else ourgrid.data[k] = grid.data[k]*255; } sprintf(buf, "font_rasters/%s_%04d_%s_2_ours.png", FontName_base.c_str(), ptsize, letter_name.c_str()); save_png(buf, ourgrid); //----------------------------------------- // Calculate difference between renders //----------------------------------------- Array2D<vect3ub> grid_dif; grid_dif.resize(g.grid_res, g.grid_res); for (int i = 0; i < grid_dif.data_size; i++) { int dif = (grid.data[i]*255 - ftgrid.data[i][0]) * 10; if (dif > 255) dif = 255; else if (dif < -255) dif = -255; #if 1 grid_dif.data[i] = 255; if (dif < 0) { grid_dif.data[i][0] += dif; grid_dif.data[i][1] += dif; } else { grid_dif.data[i][1] -= dif; grid_dif.data[i][2] -= dif; } #else grid_dif.data[i] = 0; if (dif < 0) grid_dif.data[i][2] -= dif; else grid_dif.data[i][0] += dif; #endif } sprintf(buf, "font_rasters/%s_%04d_%s_3_dif.png", FontName_base.c_str(), ptsize, letter_name.c_str()); save_png(buf, grid_dif); //printf("--== timing comparison ==--\n"); //printf("time freetype = %f\n", t_ft_stop - t_ft_start); //printf("time wavelets = %f\n", t_ours_stop - t_ours_start); //printf("times slower = %f\n", (t_ours_stop - t_ours_start) / (t_ft_stop - t_ft_start) ); if (times) { times->v[0] += t_ft_stop - t_ft_start; times->v[1] += t_ours_stop - t_ours_start; } }
int main (int argc, char** argv) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " <num-iter>" << std::endl; return EXIT_FAILURE; } const unsigned NUM_ITER = atoi(argv[1]); // open first face in the font FT_Library ft_library = 0; FT_Error error = FT_Init_FreeType(&ft_library); if (error) throw std::runtime_error("Failed to initialize FreeType2 library"); FT_Face ft_face[NUM_EXAMPLES]; FT_New_Face(ft_library, "fonts/DejaVuSerif.ttf", 0, &ft_face[ENGLISH]); FT_New_Face(ft_library, "fonts/amiri-0.104/amiri-regular.ttf", 0, &ft_face[ARABIC]); FT_New_Face(ft_library, "fonts/fireflysung-1.3.0/fireflysung.ttf", 0, &ft_face[CHINESE]); // Get our harfbuzz font structs hb_font_t *hb_ft_font[NUM_EXAMPLES]; hb_ft_font[ENGLISH] = hb_ft_font_create(ft_face[ENGLISH], NULL); hb_ft_font[ARABIC] = hb_ft_font_create(ft_face[ARABIC] , NULL); hb_ft_font[CHINESE] = hb_ft_font_create(ft_face[CHINESE], NULL); { std::cerr << "Starting ICU shaping:" << std::endl; progress_timer timer1(std::clog,"ICU shaping done"); UErrorCode err = U_ZERO_ERROR; for (unsigned i = 0; i < NUM_ITER; ++i) { for (unsigned j = 0; j < NUM_EXAMPLES; ++j) { UnicodeString text = UnicodeString::fromUTF8(texts[j]); int32_t length = text.length(); UnicodeString reordered; UnicodeString shaped; UBiDi *bidi = ubidi_openSized(length, 0, &err); ubidi_setPara(bidi, text.getBuffer(), length, UBIDI_DEFAULT_LTR, 0, &err); ubidi_writeReordered(bidi, reordered.getBuffer(length), length, UBIDI_DO_MIRRORING, &err); ubidi_close(bidi); reordered.releaseBuffer(length); u_shapeArabic(reordered.getBuffer(), length, shaped.getBuffer(length), length, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, &err); shaped.releaseBuffer(length); if (U_SUCCESS(err)) { U_NAMESPACE_QUALIFIER StringCharacterIterator iter(shaped); for (iter.setToStart(); iter.hasNext();) { UChar ch = iter.nextPostInc(); int32_t glyph_index = FT_Get_Char_Index(ft_face[j], ch); if (i == 0) { std::cerr << glyph_index << ":"; } } if (i == 0) std::cerr << std::endl; } } } } { const char **shaper_list = hb_shape_list_shapers(); for ( ;*shaper_list; shaper_list++) { std::cerr << *shaper_list << std::endl; } std::cerr << "Starting Harfbuzz shaping" << std::endl; progress_timer timer2(std::clog,"Harfbuzz shaping done"); const char* const shapers[] = { /*"ot",*/"fallback" }; hb_buffer_t *buffer(hb_buffer_create()); for (unsigned i = 0; i < NUM_ITER; ++i) { for (unsigned j = 0; j < NUM_EXAMPLES; ++j) { UnicodeString text = UnicodeString::fromUTF8(texts[j]); int32_t length = text.length(); hb_buffer_clear_contents(buffer); //hb_buffer_set_unicode_funcs(buffer.get(), hb_icu_get_unicode_funcs()); hb_buffer_pre_allocate(buffer, length); hb_buffer_add_utf16(buffer, text.getBuffer(), text.length(), 0, length); hb_buffer_set_direction(buffer, text_directions[j]); hb_buffer_set_script(buffer, scripts[j]); hb_buffer_set_language(buffer,hb_language_from_string(languages[j], std::strlen(languages[j]))); //hb_shape(hb_ft_font[j], buffer.get(), 0, 0); hb_shape_full(hb_ft_font[j], buffer, 0, 0, shapers); unsigned num_glyphs = hb_buffer_get_length(buffer); hb_glyph_info_t *glyphs = hb_buffer_get_glyph_infos(buffer, NULL); //hb_glyph_position_t *positions = hb_buffer_get_glyph_positions(buffer.get(), NULL); for (unsigned k=0; k<num_glyphs; ++k) { int32_t glyph_index = glyphs[k].codepoint; if (i == 0) { std::cerr << glyph_index << ":"; } } if (i == 0) std::cerr << std::endl; } } hb_buffer_destroy(buffer); } // cleanup for (int j=0; j < NUM_EXAMPLES; ++j) { hb_font_destroy(hb_ft_font[j]); } FT_Done_FreeType(ft_library); return EXIT_SUCCESS; }
int main (int argc, char **argv) { int i,j,found=0,m,mask=1,kmode=1,pmode=0, lc=-1, changed=0, todo=1, help=1, help_changed=0, move=0; unsigned char actchan[20]=""/*,channel[128]=""*/; FILE *fh,*fh2; char *cpt1,*cpt2; gpixel mp, mc[MAX_MASK], tp; int tsx=430, tsy=120, tdy=24, tsz=28, txw=500, tcol=TURQUOISE; int xp[MAX_MASK][8],yp[MAX_MASK][8],xw[MAX_MASK][8],yw[MAX_MASK][8],valid[MAX_MASK],cmc[MAX_MASK],xxp,xxw,yyp,yyw,nmsk=0,amsk=0; double xs=1.0, ys=1.0; time_t t1,t2; for(j=0; j<MAX_MASK; j++) { valid[j]=0; cmc[j]=BLACK; make_color(BLACK, &mc[j]); for(i=0; i<8; i++) { xp[j][i]=(1280-40)/2; xw[j][i]=40; yp[j][i]=(720-20)/2; yw[j][i]=20; } } system("pzapit -var > /tmp/logomaskset.stat"); if((fh=fopen("/tmp/logomaskset.stat","r"))!=NULL) { if(fgets(tstr,500,fh)) { TrimString(tstr); if(strlen(tstr)) { if(sscanf(tstr+strlen(tstr)-1,"%d",&pmode)!=1) { pmode=0; } } } fclose(fh); } system("touch /tmp/.logomask_kill"); fb = open(FB_DEVICE, O_RDWR); if(ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1) { printf("logomask <FBIOGET_FSCREENINFO failed>\n"); return -1; } if(ioctl(fb, FBIOGET_VSCREENINFO, &var_screeninfo) == -1) { printf("logomask <FBIOGET_VSCREENINFO failed>\n"); return -1; } if(!(lfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0))) { printf("logomask <mapping of Framebuffer failed>\n"); return -1; } //init fontlibrary if((error = FT_Init_FreeType(&library))) { printf("logomask <FT_Init_FreeType failed with Errorcode 0x%.2X>", error); munmap(lfb, fix_screeninfo.smem_len); return -1; } if((error = FTC_Manager_New(library, 1, 2, 0, &MyFaceRequester, NULL, &manager))) { printf("logomask <FTC_Manager_New failed with Errorcode 0x%.2X>\n", error); FT_Done_FreeType(library); munmap(lfb, fix_screeninfo.smem_len); return -1; } if((error = FTC_SBitCache_New(manager, &cache))) { printf("logomask <FTC_SBitCache_New failed with Errorcode 0x%.2X>\n", error); FTC_Manager_Done(manager); FT_Done_FreeType(library); munmap(lfb, fix_screeninfo.smem_len); return -1; } if((error = FTC_Manager_LookupFace(manager, FONT, &face))) { printf("logomask <FTC_Manager_Lookup_Face failed with Errorcode 0x%.2X>\n", error); FTC_Manager_Done(manager); FT_Done_FreeType(library); munmap(lfb, fix_screeninfo.smem_len); return -1; } use_kerning = FT_HAS_KERNING(face); desc.face_id = FONT; desc.flags = FT_LOAD_MONOCHROME; InitRC(); //init backbuffer if(!(lbb = malloc(fix_screeninfo.line_length*var_screeninfo.yres))) { printf("logomask <allocating of Backbuffer failed>\n"); munmap(lfb, fix_screeninfo.smem_len); return -1; } memset(lbb, 0, fix_screeninfo.line_length*var_screeninfo.yres); system("pzapit -gi > /tmp/logomask.chan"); if((fh=fopen("/tmp/logomask.chan","r"))!=NULL) { if(fgets(tstr, BUFSIZE, fh)) { TrimString(tstr); if((cpt1=strchr(tstr,' '))!=NULL) *cpt1=0; } fclose(fh); if(strlen(tstr)) { strcpy(actchan,tstr); } if((fh=fopen(CFG_FILE,"r"))!=NULL) { found=0; while(fgets(tstr, BUFSIZE, fh) && !found) { TrimString(tstr); if(strlen(tstr)) { if(strstr(tstr,actchan)!=NULL) { mask=1; nmsk=0; cpt2=strstr(tstr,",MC"); if((cpt1=strchr(tstr,','))!=NULL) { while(cpt1) { valid[nmsk]=0; if(cpt2 && sscanf(cpt2+1,"MC%8X",&mp.lpixel)==1) { cpt2=strchr(cpt2+1,','); } else { make_color(BLACK, &mp); } for(i=0; i<8 && cpt1; i++) { cpt1++; if(sscanf(cpt1,"%d,%d,%d,%d",&xxp,&xxw,&yyp,&yyw)==4) { xp[nmsk][i]=xxp; xw[nmsk][i]=xxw; yp[nmsk][i]=yyp; yw[nmsk][i]=yyw; mc[nmsk].lpixel=mp.lpixel; found=1; valid[nmsk]=1; } for(j=0; j<4 && cpt1; j++) { cpt1=strchr(cpt1+1,','); } } if(valid[nmsk]) { nmsk++; } } } } } } fclose(fh); } } if(!nmsk) { nmsk=1; valid[0]=1; } mask=nmsk; for(m=0; m<MAX_MASK; m++) { if(valid[m]) { xxp=xp[m][pmode]; xxw=xw[m][pmode]; yyp=yp[m][pmode]; yyw=yw[m][pmode]; tp.lpixel=mc[m].lpixel; RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, FILL, &tp); if(m==amsk) RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, GRID, make_color(LBLUE,&tp)); for(i=0;i<=yyw;i++) { j=(yyp+i)*fix_screeninfo.line_length+(xxp<<2); if((j+(xxw<<2))<fix_screeninfo.line_length*var_screeninfo.yres) { memcpy(lfb+j, lbb+j, xxw<<2); } } } } time(&t1); while((rc!=KEY_EXIT) && (rc!=KEY_OK)) { rc=GetRCCode(); if((rc!=-1) && (rc!=KEY_EXIT) && (rc!=KEY_OK)) { time(&t1); move=0; xxp=xp[amsk][pmode]; xxw=xw[amsk][pmode]; yyp=yp[amsk][pmode]; yyw=yw[amsk][pmode]; lpix.lpixel=mc[amsk].lpixel; switch(rc) { case KEY_LEFT: if(lc==KEY_LEFT) { xs+=0.3; } else { xs=1.0; } if(kmode) { if(xxp>0) { changed=1; xxp-=xs; } } else { if(xxw>6) { changed=1; xxw-=xs; } } move=1; break; case KEY_RIGHT: if((xxp+xxw)<(fix_screeninfo.line_length-1)) { changed=1; if(lc==KEY_RIGHT) { xs+=0.3; } else { xs=1.0; } if(kmode) { xxp+=xs; } else { xxw+=xs; } } move=1; break; case KEY_UP: if(lc==KEY_UP) { ys+=0.2; } else { ys=1.0; } if(kmode) { if(yyp>0) { changed=1; yyp-=ys; } } else { if(yyw>6) { changed=1; yyw-=ys; } } move=1; break; case KEY_DOWN: if((yyp+yyw)<(var_screeninfo.yres-1)) { changed=1; if(lc==KEY_DOWN) { ys+=0.2; } else { ys=1.0; } if(kmode) { yyp+=ys; } else { yyw+=ys; } } move=1; break; case KEY_RED: changed=1; RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, FILL, make_color(TRANSP,&tp)); for(i=0;i<=yyw;i++) { j=(yyp+i)*fix_screeninfo.line_length+(xxp<<2); if(((j+(xxw<<2)))<fix_screeninfo.line_length*var_screeninfo.yres) { memcpy(lfb+j, lbb+j, xxw<<2); } } valid[amsk]=0; nmsk--; kmode=1; if(nmsk) { todo=2; amsk=-1; for(m=0; m<MAX_MASK && amsk<0; m++) { if(valid[m]) { amsk=m; xxp=xp[amsk][pmode]; xxw=xw[amsk][pmode]; yyp=yp[amsk][pmode]; yyw=yw[amsk][pmode]; lpix.lpixel=mc[amsk].lpixel; } } } else { todo=mask=0; } break; case KEY_GREEN: if(nmsk<MAX_MASK) { todo=2; changed=1; kmode=1; amsk=-1; for(m=0; amsk<0 && m<MAX_MASK; m++) { if(!valid[m]) { amsk=m; valid[amsk]=1; nmsk++; cmc[amsk]=BLACK; make_color(BLACK, &mc[amsk]); for(i=0; i<8; i++) { xp[amsk][i]=(1280-40)/2; xw[amsk][i]=40; yp[amsk][i]=(720-20)/2; yw[amsk][i]=20; } xxp=xp[amsk][pmode]; xxw=xw[amsk][pmode]; yyp=yp[amsk][pmode]; yyw=yw[amsk][pmode]; lpix.lpixel=mc[amsk].lpixel; } } } break; case KEY_PAGEUP: if(nmsk>1) { m=amsk+1; if(m>=MAX_MASK) { m=0; } while(!valid[m]) { if(++m>=MAX_MASK) { m=0; } } RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, FILL, &lpix); amsk=m; xxp=xp[amsk][pmode]; xxw=xw[amsk][pmode]; yyp=yp[amsk][pmode]; yyw=yw[amsk][pmode]; lpix.lpixel=mc[amsk].lpixel; } break; case KEY_PAGEDOWN: if(nmsk>1) { m=amsk-1; if(m<0) { m=MAX_MASK-1; } while(!valid[m]) { if(--m<0) { m=MAX_MASK; } } RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, FILL, &lpix); amsk=m; xxp=xp[amsk][pmode]; xxw=xw[amsk][pmode]; yyp=yp[amsk][pmode]; yyw=yw[amsk][pmode]; lpix.lpixel=mc[amsk].lpixel; } break; case KEY_YELLOW: kmode=0; break; case KEY_BLUE: kmode=1; break; case KEY_1: if(nmsk) { if(mc[amsk].cpixel.rd < 0xF0) mc[amsk].cpixel.rd+=0x10; else mc[amsk].cpixel.rd=0xFF; changed=1; } break; case KEY_4: if(nmsk) { mc[amsk].cpixel.rd=0x80; changed=1; } break; case KEY_7: if(nmsk) { if(mc[amsk].cpixel.rd > 0x0F) mc[amsk].cpixel.rd-=0x10; else mc[amsk].cpixel.rd=0x00; changed=1; } break; case KEY_2: if(nmsk) { if(mc[amsk].cpixel.gn < 0xF0) mc[amsk].cpixel.gn+=0x10; else mc[amsk].cpixel.gn=0xFF; changed=1; } break; case KEY_5: if(nmsk) { mc[amsk].cpixel.gn=0x80; changed=1; } break; case KEY_8: if(nmsk) { if(mc[amsk].cpixel.gn > 0x0F) mc[amsk].cpixel.gn-=0x10; else mc[amsk].cpixel.gn=0x00; changed=1; } break; case KEY_3: if(nmsk) { if(mc[amsk].cpixel.bl < 0xF0) mc[amsk].cpixel.bl+=0x10; else mc[amsk].cpixel.bl=0xFF; changed=1; } break; case KEY_6: if(nmsk) { mc[amsk].cpixel.bl=0x80; changed=1; } break; case KEY_9: if(nmsk) { if(mc[amsk].cpixel.bl > 0x0F) mc[amsk].cpixel.bl-=0x10; else mc[amsk].cpixel.bl=0x00; changed=1; } break; case KEY_VOLUMEDOWN: if(nmsk) { if(mc[amsk].cpixel.tr < 0xF8) mc[amsk].cpixel.tr+=0x08; else mc[amsk].cpixel.tr=0xFF; changed=1; } break; case KEY_VOLUMEUP: if(nmsk) { if(mc[amsk].cpixel.tr > 0x08) mc[amsk].cpixel.tr-=0x08; else mc[amsk].cpixel.tr=0x00; changed=1; } break; case KEY_MUTE: if(nmsk) { if(++cmc[amsk]>LTURQUOISE) cmc[amsk]=BLACK; make_color(cmc[amsk], &mc[amsk]); changed=1; } break; case KEY_HELP: help_changed=1; break; } lc=rc; lpix.lpixel=mc[amsk].lpixel; if(mask || todo==2) { RenderBox(xp[amsk][pmode], yp[amsk][pmode], xp[amsk][pmode]+xw[amsk][pmode], yp[amsk][pmode]+yw[amsk][pmode], FILL, make_color(TRANSP, &tp)); for(i=0;i<=yw[amsk][pmode];i++) { j=(yp[amsk][pmode]+i)*fix_screeninfo.line_length+(xp[amsk][pmode]<<2); if((j+(xw[amsk][pmode]<<2))<fix_screeninfo.line_length*var_screeninfo.yres) { memcpy(lfb+j, lbb+j, (xw[amsk][pmode]+1)<<2); } } xp[amsk][pmode]=xxp; xw[amsk][pmode]=xxw; yp[amsk][pmode]=yyp; yw[amsk][pmode]=yyw; for(m=0; mask && m<MAX_MASK; m++) { if(valid[m]) { xxp=xp[m][pmode]; xxw=xw[m][pmode]; yyp=yp[m][pmode]; yyw=yw[m][pmode]; tp.lpixel=mc[m].lpixel; RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, FILL, ((m==amsk) && move)?make_color(TRANSP, &tp):&tp); if(m==amsk) RenderBox(xxp, yyp, xxp+xxw, yyp+yyw, GRID, make_color((kmode)?LBLUE:LYELLOW,&tp)); for(i=0;i<=yyw;i++) { j=(yyp+i)*fix_screeninfo.line_length+(xxp<<2); if((j+(xxw<<2))<fix_screeninfo.line_length*var_screeninfo.yres) { memcpy(lfb+j, lbb+j, (xxw+1)<<2); } } } } } } time(&t2); if((t2-t1)>1) { xs=1.0; ys=1.0; tsy=120; if(move) { RenderBox(xp[amsk][pmode], yp[amsk][pmode], xp[amsk][pmode]+xw[amsk][pmode], yp[amsk][pmode]+yw[amsk][pmode], FILL, &mc[amsk]); RenderBox(xp[amsk][pmode], yp[amsk][pmode], xp[amsk][pmode]+xw[amsk][pmode], yp[amsk][pmode]+yw[amsk][pmode], GRID, make_color((kmode)?LBLUE:LYELLOW,&tp)); } move=0; if(help_changed) { help^=1; } if(help) { RenderBox(tsx,tsy,tsx+txw,tsy+21*tdy,FILL,make_color(TRANSP, &tp)); if(nmsk) RenderBox(xp[amsk][pmode], yp[amsk][pmode], xp[amsk][pmode]+xw[amsk][pmode], yp[amsk][pmode]+yw[amsk][pmode], GRID, make_color((kmode)?LBLUE:LYELLOW, &tp)); RenderString("Maskensteuerung", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Blau : Umschalten auf Positionseinstellung", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Gelb : Umschalten auf Größeneinstellung", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Grün : Maske hinzufügen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Rot : Maske löschen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("PgUp : nächste Maske auswählen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("PgDn : vorherige Maske auswählen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Maskenfarbe", tsx, tsy+=(2*tdy), txw, LEFT, tsz, tcol); RenderString("Mute : Maskenfarbe aus Vorgabe auswählen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("1,4,7 : Farbton Rot erhöhen, auf Mitte setzen, verringern", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("2,5,8 : Farbton Grün erhöhen, auf Mitte setzen, verringern", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("3,6,9 : Farbton Blau erhöhen, auf Mitte setzen, verringern", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Vol + : Transparenz erhöhen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Vol - : Transparenz verringern", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Allgemein", tsx, tsy+=(2*tdy), txw, LEFT, tsz, tcol); RenderString("? : Hilfetext ein/ausschalten", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("Exit : Abbrechen", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); RenderString("OK : Speichern und Beenden", tsx, tsy+=tdy, txw, LEFT, tsz, tcol); } else { if(help_changed) { RenderBox(tsx, tsy, tsx+txw, tsy+21*tdy, FILL, make_color(TRANSP, &tp)); if(nmsk) RenderBox(xp[amsk][pmode], yp[amsk][pmode], xp[amsk][pmode]+xw[amsk][pmode], yp[amsk][pmode]+yw[amsk][pmode], GRID, make_color((kmode)?LBLUE:LYELLOW, &tp)); } } help_changed=0; memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres); } } if(rc==KEY_EXIT) { changed=0; todo=0; } if(rc==KEY_OK && changed) { if((fh2=fopen("/tmp/logomask.conf","w"))!=NULL) { fh=fopen(CFG_FILE,"r"); while(fh && fgets(tstr, BUFSIZE, fh)) { TrimString(tstr); if(strlen(tstr)) { if(strstr(tstr,actchan)==NULL) { fprintf(fh2,"%s\n",tstr); } } } if(fh) { fclose(fh); } if(todo) { fprintf(fh2,"%s",actchan); for(j=0; j<MAX_MASK; j++) { if(valid[j]) { for(i=0; i<8; i++) { fprintf(fh2,",%d,%d,%d,%d",xp[j][i],xw[j][i],yp[j][i],yw[j][i]); } } } for(j=0; j<MAX_MASK; j++) { if(valid[j]) { fprintf(fh2,",MC%08X",mc[j].lpixel); } } fprintf(fh2,",\n"); } fclose(fh2); remove(CFG_FILE); system("mv /tmp/logomask.conf /var/tuxbox/config/logomask.conf"); } } free(lbb); munmap(lfb, fix_screeninfo.smem_len); close(fb); CloseRC(); remove("/tmp/.logomask_kill"); remove("/tmp/logomaskset.*"); system("logomask &"); return 0; }
/***************************************************************************** * Create: allocates osd-text video thread output method ***************************************************************************** * This function allocates and initializes a Clone vout method. *****************************************************************************/ static int Create( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys; char *psz_fontfile = NULL; int i, i_error; int i_fontsize = 0; vlc_value_t val; /* Allocate structure */ p_sys = malloc( sizeof( filter_sys_t ) ); if( !p_sys ) { msg_Err( p_filter, "out of memory" ); return VLC_ENOMEM; } p_sys->p_face = 0; p_sys->p_library = 0; for( i = 0; i < 256; i++ ) { p_sys->pi_gamma[i] = (uint8_t)( pow( (double)i * 255.0f, 0.5f ) ); } var_Create( p_filter, "freetype-font", VLC_VAR_STRING | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Create( p_filter, "freetype-rel-fontsize", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); /* Look what method was requested */ var_Get( p_filter, "freetype-font", &val ); psz_fontfile = val.psz_string; if( !psz_fontfile || !*psz_fontfile ) { if( psz_fontfile ) free( psz_fontfile ); psz_fontfile = (char *)malloc( PATH_MAX + 1 ); #ifdef WIN32 GetWindowsDirectory( psz_fontfile, PATH_MAX + 1 ); strcat( psz_fontfile, "\\fonts\\arial.ttf" ); #elif SYS_DARWIN strcpy( psz_fontfile, DEFAULT_FONT ); #else msg_Err( p_filter, "user didn't specify a font" ); goto error; #endif } i_error = FT_Init_FreeType( &p_sys->p_library ); if( i_error ) { msg_Err( p_filter, "couldn't initialize freetype" ); goto error; } i_error = FT_New_Face( p_sys->p_library, psz_fontfile ? psz_fontfile : "", 0, &p_sys->p_face ); if( i_error == FT_Err_Unknown_File_Format ) { msg_Err( p_filter, "file %s have unknown format", psz_fontfile ); goto error; } else if( i_error ) { msg_Err( p_filter, "failed to load font file %s", psz_fontfile ); goto error; } i_error = FT_Select_Charmap( p_sys->p_face, ft_encoding_unicode ); if( i_error ) { msg_Err( p_filter, "Font has no unicode translation table" ); goto error; } p_sys->i_use_kerning = FT_HAS_KERNING( p_sys->p_face ); var_Get( p_filter, "freetype-fontsize", &val ); if( val.i_int ) { i_fontsize = val.i_int; } else { var_Get( p_filter, "freetype-rel-fontsize", &val ); i_fontsize = (int)p_filter->fmt_out.video.i_height / val.i_int; } if( i_fontsize <= 0 ) { msg_Warn( p_filter, "Invalid fontsize, using 12" ); i_fontsize = 12; } msg_Dbg( p_filter, "Using fontsize: %i", i_fontsize); i_error = FT_Set_Pixel_Sizes( p_sys->p_face, 0, i_fontsize ); if( i_error ) { msg_Err( p_filter, "couldn't set font size to %d", i_fontsize ); goto error; } if( psz_fontfile ) free( psz_fontfile ); p_filter->pf_render_string = RenderText; p_filter->p_sys = p_sys; return VLC_SUCCESS; error: if( p_sys->p_face ) FT_Done_Face( p_sys->p_face ); if( p_sys->p_library ) FT_Done_FreeType( p_sys->p_library ); if( psz_fontfile ) free( psz_fontfile ); free( p_sys ); return VLC_EGENERIC; }
static void dump_dependencies(void) { #ifdef __GNUC__ g_print ("Compiler: GCC " __VERSION__ "\n"); #elif defined _MSC_VER g_print ("Compiler: MSC %d\n", _MSC_VER); #else g_print ("Compiler: unknown\n"); #endif /* some flags/defines which may be interesting */ g_print (" with : " #ifdef G_THREADS_ENABLED "threads " #endif #ifdef HAVE_CAIRO "cairo " #endif #ifdef HAVE_GNOME "gnome " #endif #ifdef HAVE_LIBART "libart " #endif #ifdef HAVE_PANGOCAIRO "pangocairo " #endif "\n"); /* print out all those dependies, both compile and runtime if possible * Note: this is not meant to be complete but does only include libaries * which may or have cause(d) us trouble in some versions */ g_print ("Library versions (at compile time)\n"); #ifdef HAVE_LIBPNG g_print ("libpng : %s (%s)\n", png_get_header_ver(NULL), PNG_LIBPNG_VER_STRING); #endif #ifdef HAVE_FREETYPE { FT_Library ft_library; FT_Int ft_major_version; FT_Int ft_minor_version; FT_Int ft_micro_version; if (FT_Init_FreeType (&ft_library) == 0) { FT_Library_Version (ft_library, &ft_major_version, &ft_minor_version, &ft_micro_version); g_print ("freetype: %d.%d.%d\n", ft_major_version, ft_minor_version, ft_micro_version); FT_Done_FreeType (ft_library); } else g_print ("freetype: ?.?.?\n"); } #endif { const gchar* libxml_rt_version = "?"; #if 0 /* this is stupid, does not compile on Linux: * app_procs.c:504: error: expected identifier before '(' token * * In fact libxml2 has different ABI for LIBXML_THREAD_ENABLED, this code only compiles without * threads enabled, but apparently it does only work when theay are. */ xmlInitParser(); if (xmlGetGlobalState()) libxml_rt_version = xmlGetGlobalState()->xmlParserVersion; #endif libxml_rt_version = xmlParserVersion; if (atoi(libxml_rt_version)) g_print ("libxml : %d.%d.%d (%s)\n", atoi(libxml_rt_version) / 10000, atoi(libxml_rt_version) / 100 % 100, atoi(libxml_rt_version) % 100, LIBXML_DOTTED_VERSION); else /* may include "extra" */ g_print ("libxml : %s (%s)\n", libxml_rt_version ? libxml_rt_version : "??", LIBXML_DOTTED_VERSION); } g_print ("glib : %d.%d.%d (%d.%d.%d)\n", glib_major_version, glib_minor_version, glib_micro_version, GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); #ifdef PANGO_VERSION_ENCODE g_print ("pango : %s (%d.%d.%d)\n", pango_version_string(), PANGO_VERSION_MAJOR, PANGO_VERSION_MINOR, PANGO_VERSION_MICRO); #else g_print ("pango : version not available (>= 1.14.x)\n"); /* Pango did not provide such */ #endif #if HAVE_CAIRO # ifdef CAIRO_VERSION_STRING g_print ("cairo : %s (%s)\n", cairo_version_string(), CAIRO_VERSION_STRING); # else g_print ("cairo : %s (%d.%d.%d)\n", cairo_version_string(), CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR, CAIRO_VERSION_MICRO); # endif #endif #if 0 { gchar linkedname[1024]; gint len = 0; /* relying on PREFIX is wrong */ if ((len = readlink (PREFIX "/lib/libpango-1.0.so", linkedname, 1023)) > 0) { /* man 2 readlink : does not append a NUL character */ linkedname[len] = '\0'; g_print ("%s/%s\n", PREFIX, linkedname); } } #endif g_print ("gtk+ : %d.%d.%d (%d.%d.%d)\n", gtk_major_version, gtk_minor_version, gtk_micro_version, GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); #if 0 /* we could read $PREFIX/share/gnome-about/gnome-version.xml * but is it worth the effort ? */ g_print ("gnome : %d.%d.%d (%d.%d.%d)\n" gnome_major_version, gnome_minor_version, gnome_micro_version, GNOME_MAJOR_VERSION, GNOME_MINOR_VERSION, GNOME_MICRO_VERSION); #endif }
//----------------------------------------------------------------------------- // Get the list of available font filenames, and load the name for each of // them. Only that, though, not the glyphs too. //----------------------------------------------------------------------------- TtfFontList::TtfFontList() { FT_Init_FreeType(&fontLibrary); }
Font::LibraryParameter::LibraryParameter() { FT_Error error = FT_Init_FreeType(&library); // Throw an exception if the library failed //if (error) }
bool Graphics::loadFonts() { return (!FT_Init_FreeType(&_fontLibrary) && loadFont(FONT_FACE_REGULAR, _fontFace, &_fontBuffer) && loadFont(FONT_FACE_BOLD, _fontFaceB, &_fontBufferB)); }
int main(int argc, char **argv) { FT_Error error; FT_Library library; FT_Face face; GFile *file; gchar *font_file, *title; gint row; GtkWidget *window, *hbox, *table, *swin, *drawing_area; GdkColor white = { 0, 0xffff, 0xffff, 0xffff }; GtkWidget *button, *align; bindtextdomain(GETTEXT_PACKAGE, MATELOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); gtk_init(&argc, &argv); if (argc != 2) { g_printerr(_("usage: %s fontfile\n"), argv[0]); return 1; } if (!XftInitFtLibrary()) { g_printerr("could not initialise freetype library\n"); return 1; } error = FT_Init_FreeType(&library); if (error) { g_printerr("could not initialise freetype\n"); return 1; } file = g_file_new_for_commandline_arg (argv[1]); font_file = g_file_get_uri (file); g_object_unref (file); if (!font_file) { g_printerr("could not parse argument into a URI\n"); return 1; } error = FT_New_Face_From_URI(library, font_file, 0, &face); if (error) { g_printerr("could not load face '%s'\n", font_file); return 1; } window = gtk_window_new(GTK_WINDOW_TOPLEVEL); title = g_strconcat(face->family_name, face->style_name ? ", " : "", face->style_name, NULL); gtk_window_set_title(GTK_WINDOW(window), title); set_icon(GTK_WINDOW(window), font_file); g_free(title); gtk_window_set_resizable(GTK_WINDOW(window), TRUE); hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), hbox); swin = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swin), GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER); gtk_box_pack_start(GTK_BOX(hbox), swin, TRUE, TRUE, 0); drawing_area = gtk_drawing_area_new(); gtk_widget_modify_bg(drawing_area, GTK_STATE_NORMAL, &white); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(swin), drawing_area); #if !GTK_CHECK_VERSION (3, 0, 0) g_signal_connect (drawing_area, "realize", G_CALLBACK(create_text_pixmap), face); #endif /* set the minimum size on the scrolled window to prevent * unnecessary scrolling */ gtk_widget_set_size_request(swin, 500, -1); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); table = gtk_table_new(1, 2, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 5); gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, TRUE, 0); row = 0; add_face_info(table, &row, font_file, face); /* add install button */ align = gtk_alignment_new (1.0, 0.5, 0.0, 0.0); gtk_table_attach (GTK_TABLE (table), align, 0, 2, row, row + 1, GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0); button = gtk_button_new_with_mnemonic (_("I_nstall Font")); g_signal_connect (button, "clicked", G_CALLBACK (install_button_clicked_cb), font_file); gtk_container_add (GTK_CONTAINER (align), button); gtk_table_set_col_spacings(GTK_TABLE(table), 8); gtk_table_set_row_spacings(GTK_TABLE(table), 2); gtk_widget_show_all(window); gtk_main(); return 0; }
Error DynamicFontAtSize::_load() { int error = FT_Init_FreeType( &library ); ERR_EXPLAIN(TTR("Error initializing FreeType.")); ERR_FAIL_COND_V( error !=0, ERR_CANT_CREATE ); if (font->font_path!=String()) { FileAccess *f=FileAccess::open(font->font_path,FileAccess::READ); ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); memset(&stream,0,sizeof(FT_StreamRec)); stream.base=NULL; stream.size=f->get_len(); stream.pos=0; stream.descriptor.pointer=f; stream.read=_ft_stream_io; stream.close=_ft_stream_close; FT_Open_Args fargs; memset(&fargs,0,sizeof(FT_Open_Args)); fargs.flags=FT_OPEN_STREAM; fargs.stream=&stream; error = FT_Open_Face( library,&fargs,0,&face); } else if (font->font_mem) { memset(&stream,0,sizeof(FT_StreamRec)); stream.base=(unsigned char*)font->font_mem; stream.size=font->font_mem_size; stream.pos=0; FT_Open_Args fargs; memset(&fargs,0,sizeof(FT_Open_Args)); fargs.memory_base=(unsigned char*)font->font_mem; fargs.memory_size=font->font_mem_size; fargs.flags= FT_OPEN_MEMORY; fargs.stream=&stream; error = FT_Open_Face( library,&fargs,0,&face); } else { ERR_EXPLAIN("DynamicFont uninitialized"); ERR_FAIL_V(ERR_UNCONFIGURED); } //error = FT_New_Face( library, src_path.utf8().get_data(),0,&face ); if ( error == FT_Err_Unknown_File_Format ) { ERR_EXPLAIN(TTR("Unknown font format.")); FT_Done_FreeType( library ); } else if ( error ) { ERR_EXPLAIN(TTR("Error loading font.")); FT_Done_FreeType( library ); } ERR_FAIL_COND_V(error,ERR_FILE_CANT_OPEN); /*error = FT_Set_Char_Size(face,0,64*size,512,512); if ( error ) { FT_Done_FreeType( library ); ERR_EXPLAIN(TTR("Invalid font size.")); ERR_FAIL_COND_V( error, ERR_INVALID_PARAMETER ); }*/ error = FT_Set_Pixel_Sizes(face,0,size); ascent=face->size->metrics.ascender>>6; descent=-face->size->metrics.descender>>6; linegap=0; //print_line("ASCENT: "+itos(ascent)+" descent "+itos(descent)+" hinted: "+itos(face->face_flags&FT_FACE_FLAG_HINTER)); valid=true; return OK; }
/* initialise font handling */ bool fb_font_init(void) { FT_Error error; FT_ULong max_cache_size; FT_UInt max_faces = 6; fb_faceid_t *fb_face; LOG(("Freetype init...")); nsoptions.fb_font_monochrome = false; nsoptions.fb_font_cachesize = 2048; nsoptions.fb_face_sans_serif = NULL; nsoptions.fb_face_sans_serif_bold = NULL; nsoptions.fb_face_sans_serif_italic = NULL; nsoptions.fb_face_sans_serif_italic_bold = NULL; nsoptions.fb_face_serif = NULL; nsoptions.fb_face_serif_bold = NULL; nsoptions.fb_face_monospace = NULL; nsoptions.fb_face_monospace_bold = NULL; nsoptions.fb_face_cursive = NULL; nsoptions.fb_face_fantasy = NULL; /* freetype library initialise */ error = FT_Init_FreeType( &library ); if (error) { LOG(("Freetype could not initialised (code %d)\n", error)); return false; } /* set the Glyph cache size up */ max_cache_size = nsoption_int(fb_font_cachesize) * 1024; if (max_cache_size < CACHE_MIN_SIZE) { max_cache_size = CACHE_MIN_SIZE; } LOG(("Freetype cache...")); DBG("Ft cache\n"); /* cache manager initialise */ error = FTC_Manager_New(library, max_faces, 0, max_cache_size, ft_face_requester, NULL, &ft_cmanager); if (error) { LOG(("Freetype could not initialise cache manager (code %d)\n", error)); FT_Done_FreeType(library); return false; } LOG(("Freetype map cache...")); DBG("Ft map cache\n"); error = FTC_CMapCache_New(ft_cmanager, &ft_cmap_cache); error = FTC_ImageCache_New(ft_cmanager, &ft_image_cache); /* need to obtain the generic font faces */ LOG(("Freetype load fonts...")); DBG("Ft load fonts\n"); /* Start with the sans serif font */ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif), "sans_serif.ttf", NETSURF_FB_FONT_SANS_SERIF); if (fb_face == NULL) { LOG(("Freetype load fonts failed due SANS unavailable :(...")); DBG("Ft Z:(((\n"); /* The sans serif font is the default and must be found. */ LOG(("Could not find the default font\n")); FTC_Manager_Done(ft_cmanager); FT_Done_FreeType(library); return false; } else { fb_faces[FB_FACE_SANS_SERIF] = fb_face; } LOG(("Freetype loaded sans..")); DBG("Ft sans loaded:)\n"); /* Bold sans serif face */ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_bold), "sans_serif_bold.ttf", NETSURF_FB_FONT_SANS_SERIF_BOLD); if (fb_face == NULL) { /* seperate bold face unavailabe use the normal weight version */ fb_faces[FB_FACE_SANS_SERIF_BOLD] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_SANS_SERIF_BOLD] = fb_face; } /* Italic sans serif face */ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_italic), "sans_serif_italic.ttf", NETSURF_FB_FONT_SANS_SERIF_ITALIC); if (fb_face == NULL) { /* seperate italic face unavailabe use the normal weight version */ fb_faces[FB_FACE_SANS_SERIF_ITALIC] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_SANS_SERIF_ITALIC] = fb_face; } /* Bold italic sans serif face */ fb_face = fb_new_face(nsoption_charp(fb_face_sans_serif_italic_bold), "sans_serif_italic_bold.ttf", NETSURF_FB_FONT_SANS_SERIF_ITALIC_BOLD); if (fb_face == NULL) { /* seperate italic face unavailabe use the normal weight version */ fb_faces[FB_FACE_SANS_SERIF_ITALIC_BOLD] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_SANS_SERIF_ITALIC_BOLD] = fb_face; } /* serif face */ fb_face = fb_new_face(nsoption_charp(fb_face_serif), "serif.ttf", NETSURF_FB_FONT_SERIF); if (fb_face == NULL) { /* serif face unavailabe use the default */ fb_faces[FB_FACE_SERIF] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_SERIF] = fb_face; } /* bold serif face*/ fb_face = fb_new_face(nsoption_charp(fb_face_serif_bold), "serif_bold.ttf", NETSURF_FB_FONT_SERIF_BOLD); if (fb_face == NULL) { /* bold serif face unavailabe use the normal weight */ fb_faces[FB_FACE_SERIF_BOLD] = fb_faces[FB_FACE_SERIF]; } else { fb_faces[FB_FACE_SERIF_BOLD] = fb_face; } /* monospace face */ fb_face = fb_new_face(nsoption_charp(fb_face_monospace), "monospace.ttf", NETSURF_FB_FONT_MONOSPACE); if (fb_face == NULL) { /* serif face unavailabe use the default */ fb_faces[FB_FACE_MONOSPACE] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_MONOSPACE] = fb_face; } /* bold monospace face*/ fb_face = fb_new_face(nsoption_charp(fb_face_monospace_bold), "monospace_bold.ttf", NETSURF_FB_FONT_MONOSPACE_BOLD); if (fb_face == NULL) { /* bold serif face unavailabe use the normal weight */ fb_faces[FB_FACE_MONOSPACE_BOLD] = fb_faces[FB_FACE_MONOSPACE]; } else { fb_faces[FB_FACE_MONOSPACE_BOLD] = fb_face; } /* cursive face */ fb_face = fb_new_face(nsoption_charp(fb_face_cursive), "cursive.ttf", NETSURF_FB_FONT_CURSIVE); if (fb_face == NULL) { /* cursive face unavailabe use the default */ fb_faces[FB_FACE_CURSIVE] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_CURSIVE] = fb_face; } /* fantasy face */ fb_face = fb_new_face(nsoption_charp(fb_face_fantasy), "fantasy.ttf", NETSURF_FB_FONT_FANTASY); if (fb_face == NULL) { /* fantasy face unavailabe use the default */ fb_faces[FB_FACE_FANTASY] = fb_faces[FB_FACE_SANS_SERIF]; } else { fb_faces[FB_FACE_FANTASY] = fb_face; } LOG(("Freetype fonts ready...")); DBG("Ft ready :)\n"); /* set the default render mode */ if (nsoption_bool(fb_font_monochrome) == true) ft_load_type = FT_LOAD_MONOCHROME; /* faster but less pretty */ else ft_load_type = 0; return true; }
// ------------------------------------------------------------- load_glyph --- texture_glyph_t * load_glyph( const char * filename, const wchar_t charcode, const float highres_size, const float lowres_size, const float padding ) { size_t i, j; FT_Library library; FT_Face face; FT_Init_FreeType( &library ); FT_New_Face( library, filename, 0, &face ); FT_Select_Charmap( face, FT_ENCODING_UNICODE ); FT_UInt glyph_index = FT_Get_Char_Index( face, charcode ); // Render glyph at high resolution (highres_size points) FT_Set_Char_Size( face, highres_size*64, 0, 72, 72 ); FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT); FT_GlyphSlot slot = face->glyph; FT_Bitmap bitmap = slot->bitmap; // Allocate high resolution buffer size_t highres_width = bitmap.width + 2*padding*highres_size; size_t highres_height = bitmap.rows + 2*padding*highres_size; double * highres_data = (double *) malloc( highres_width*highres_height*sizeof(double) ); memset( highres_data, 0, highres_width*highres_height*sizeof(double) ); // Copy high resolution bitmap with padding and normalize values for( j=0; j < bitmap.rows; ++j ) { for( i=0; i < bitmap.width; ++i ) { int x = i + padding; int y = j + padding; highres_data[y*highres_width+x] = bitmap.buffer[j*bitmap.width+i]/255.0; } } // Compute distance map distance_map( highres_data, highres_width, highres_height ); // Allocate low resolution buffer size_t lowres_width = round(highres_width * lowres_size/highres_size); size_t lowres_height = round(highres_height * lowres_width/(float) highres_width); double * lowres_data = (double *) malloc( lowres_width*lowres_height*sizeof(double) ); memset( lowres_data, 0, lowres_width*lowres_height*sizeof(double) ); // Scale down highres buffer into lowres buffer resize( highres_data, highres_width, highres_height, lowres_data, lowres_width, lowres_height ); // Convert the (double *) lowres buffer into a (unsigned char *) buffer and // rescale values between 0 and 255. unsigned char * data = (unsigned char *) malloc( lowres_width*lowres_height*sizeof(unsigned char) ); for( j=0; j < lowres_height; ++j ) { for( i=0; i < lowres_width; ++i ) { double v = lowres_data[j*lowres_width+i]; data[j*lowres_width+i] = (int) (255*(1-v)); } } // Compute new glyph information from highres value float ratio = lowres_size / highres_size; size_t pitch = lowres_width * sizeof( unsigned char ); // Create glyph texture_glyph_t * glyph = texture_glyph_new( ); glyph->offset_x = (slot->bitmap_left + padding*highres_width) * ratio; glyph->offset_y = (slot->bitmap_top + padding*highres_height) * ratio; glyph->width = lowres_width; glyph->height = lowres_height; glyph->charcode = charcode; /* printf( "Glyph width: %ld\n", glyph->width ); printf( "Glyph height: %ld\n", glyph->height ); printf( "Glyph offset x: %d\n", glyph->offset_x ); printf( "Glyph offset y: %d\n", glyph->offset_y ); */ ivec4 region = texture_atlas_get_region( atlas, glyph->width, glyph->height ); /* printf( "Region x : %d\n", region.x ); printf( "Region y : %d\n", region.y ); printf( "Region width : %d\n", region.width ); printf( "Region height : %d\n", region.height ); */ texture_atlas_set_region( atlas, region.x, region.y, glyph->width, glyph->height, data, pitch ); glyph->s0 = region.x/(float)atlas->width; glyph->t0 = region.y/(float)atlas->height; glyph->s1 = (region.x + glyph->width)/(float)atlas->width; glyph->t1 = (region.y + glyph->height)/(float)atlas->height; FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT); glyph->advance_x = ratio * face->glyph->advance.x/64.0; glyph->advance_y = ratio * face->glyph->advance.y/64.0; /* printf( "Advance x : %f\n", glyph->advance_x ); printf( "Advance y : %f\n", glyph->advance_y ); */ free( highres_data ); free( lowres_data ); free( data ); return glyph; }
/** * Init and load font **/ OpenGLFont::OpenGLFont(RenderOpenGL* render, string name, Mod* mod, float size) { int error; // Basics this->pmpl = new OpenGLFont_Implementation(); this->render = render; this->size = size; // Init freetype // TODO: Should we share the tf ptr between OpenGLFont instances error = FT_Init_FreeType(&this->pmpl->ft); if (error) { reportFatalError("Freetype: Unable to init library."); } // On Linux, the system font is found using fontconfig #if defined(__linux__) FcConfig* config = FcInitLoadConfigAndFonts(); FcPattern* pat = FcPatternBuild( NULL, FC_FAMILY, FcTypeString, reinterpret_cast<const char*>(name.c_str()), NULL ); FcConfigSubstitute(config, pat, FcMatchPattern); FcDefaultSubstitute(pat); FcResult result; FcPattern* font = FcFontMatch(config, pat, &result); if (font == NULL) { reportFatalError("Fontconfig: Unable to find font " + name); } FcChar8* filename = NULL; if (FcPatternGetString(font, FC_FILE, 0, &filename) != FcResultMatch) { reportFatalError("Fontconfig: No filename in fontconfig match"); } error = FT_New_Face(this->pmpl->ft, reinterpret_cast<const char*>(filename), 0, &this->pmpl->face); FcPatternDestroy(font); FcPatternDestroy(pat); #else // All other systems use a file in the cr/ mod Sint64 len; name.append(".ttf"); this->pmpl->buf = mod->loadBinary(name, &len); if (this->pmpl->buf == NULL) { reportFatalError("Freetype: Unable to load data"); } error = FT_New_Memory_Face(this->pmpl->ft, (const FT_Byte *) this->pmpl->buf, (FT_Long)len, 0, &this->pmpl->face); #endif // Handle errors if (error == FT_Err_Unknown_File_Format) { reportFatalError("Freetype: Unsupported font format"); } else if (error) { reportFatalError("Freetype: Unable to load font"); } // Set character size error = FT_Set_Char_Size(this->pmpl->face, 0, size * 64, 72, 72); if (error) { reportFatalError("Freetype: Unable to load font size"); } }
bool FT2Font::init() { unsigned err; if( ( err = FT_Init_FreeType( &m_lib ) ) ) { msg_Err( getIntf(), "failed to initialize freetype (%s)", ft2_strerror( err ) ); return false; } FILE *file = fopen( m_name.c_str(), "rb" ); if( !file ) { msg_Dbg( getIntf(), "failed to open font %s (%s)", m_name.c_str(), strerror(errno) ); return false; } msg_Dbg( getIntf(), "loading font %s", m_name.c_str() ); fseek( file, 0, SEEK_END ); long size = ftell( file ); rewind( file ); if( -1==size ) { msg_Dbg( getIntf(), "fseek loading font %s (%s)", m_name.c_str(), strerror(errno) ); fclose( file ); return false; } m_buffer = new (std::nothrow) char[size]; if( !m_buffer ) { fclose( file ); return false; } if( fread( m_buffer, size, 1, file ) != 1 ) { msg_Err( getIntf(), "unexpected result for read" ); fclose( file ); return false; } fclose( file ); err = FT_New_Memory_Face( m_lib, (const FT_Byte*)m_buffer, size, 0, &m_face ); if ( err == FT_Err_Unknown_File_Format ) { msg_Err( getIntf(), "unsupported font format (%s)", m_name.c_str() ); return false; } else if ( err ) { msg_Err( getIntf(), "error opening font %s (%s)", m_name.c_str(), ft2_strerror(err) ); return false; } // Select the charset if( ( err = FT_Select_Charmap( m_face, ft_encoding_unicode ) ) ) { msg_Err( getIntf(), "font %s has no UNICODE table (%s)", m_name.c_str(), ft2_strerror(err) ); return false; } // Set the pixel size if( ( err = FT_Set_Pixel_Sizes( m_face, 0, m_size ) ) ) { msg_Warn( getIntf(), "cannot set a pixel size of %d for %s (%s)", m_size, m_name.c_str(), ft2_strerror(err) ); } // Get the font metrucs m_height = m_face->size->metrics.height >> 6; m_ascender = m_face->size->metrics.ascender >> 6; m_descender = m_face->size->metrics.descender >> 6; return true; }
FreeTypeLib::FreeTypeLib() { FT_Init_FreeType(&lib); }
/** * Initialize a new console */ Console* new_Console(cairo_t* context, double font_size) { //printf("Console::Console(cairo_t@%p)\n", context); Console* self; self = malloc(sizeof(Console)); self->head = null; self->tail = null; self->cursor = null; self->width = default_width; self->height = default_height; self->pad = 4; self->font_filename = "./Monaco_Linux.ttf"; /* TODO */ self->font_size = font_size; self->transparency = 1.0; self->antialias_text = false; self->antialias_graphics = true; /* initialize lithp, cairo - and define callbacks */ self->lithp = new_LithpInterpreter(); char* cairo_init [] = { //"(set 'libcairo (xl:dlopen \"libcairo.dylib\"))", //"(set 'libcairo (xl:dlopen \"libcairo.so.2\"))", //"(set 'libcairo (xl:dlopen \"/Users/antoine/Projects/phlo/install/lib/libcairo.dylib\"))", #if defined(__linux__) "(set 'libcairo (xl:dlopen \"libcairo.so.2\"))", #elif defined(__APPLE__) && defined(__MACH__) "(set 'libcairo (xl:dlopen \"libcairo.dylib\"))", #endif "(set 'cairo:set-source-rgb (xl:dlsym libcairo \"cairo_set_source_rgb\"))", "(set 'cairo:rectangle (xl:dlsym libcairo \"cairo_rectangle\"))", "(set 'cairo:fill (xl:dlsym libcairo \"cairo_fill\"))", "(set 'cairo:translate (xl:dlsym libcairo \"cairo_translate\"))", "(set 'cairo:rotate (xl:dlsym libcairo \"cairo_rotate\"))", "(set 'cairo:move-to (xl:dlsym libcairo \"cairo_move_to\"))", "(set 'cairo:set-source-rgba (xl:dlsym libcairo \"cairo_set_source_rgba\"))", "(set 'console:width 492)", "(set 'console:height 344)", "(set 'pi 3.141592)", "(set 'pretty '(lambda (cr arc theta) " " (cond ((lte arc 0.0) 0.0) " " ('t (progn " " (cairo:rotate cr theta) " " (cairo:rectangle cr 20.0 20.0 140.0 20.0) " " (cairo:fill cr) " " (pretty cr (sub arc theta) theta)))))) ", "(set 'console:expose-event '(lambda (context) " " (cairo:set-source-rgb context 0.5 0.5 1.0) " " (cairo:translate context (div console:width 2.0) (div console:height 2.0))" " (pretty context (mul pi 2.0) (div pi 4.0))))", //"(set 'console:expose-event '(lambda (context) ()))", null }; for (size_t t = 0; cairo_init[t] != null; t++) { Expression* callback = Expression_parse_utf8(cairo_init[t], null, &self->lithp->symbol_list); _gc_protect(callback); Expression_eval(callback, self->lithp->environment); _gc_unprotect(callback); } /* initialize and configure console font */ FT_Library library; int error = FT_Init_FreeType(&library); if (error) { perror("Could not open FreeType library"); exit(EXIT_FAILURE); } self->font_face = malloc(sizeof(FT_Face*)); error = FT_New_Face(library, self->font_filename, 0, self->font_face); if (error) { perror("Could not open font"); exit(EXIT_FAILURE); } cairo_set_font_face(context, cairo_ft_font_face_create_for_ft_face(*self->font_face, 0)); cairo_set_font_size(context, self->font_size); cairo_font_options_t* font_options = cairo_font_options_create(); cairo_get_font_options(context, font_options); if (self->antialias_text) { cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_NONE); } cairo_set_font_options(context, font_options); self->font_extents = malloc(sizeof(cairo_font_extents_t)); cairo_font_extents(context, self->font_extents); /* some sample text */ //wchar_t* test_text = L"ABCDEFGHIJKLM\nNOPQRSTUVWXYZ\nabcdefghijklm\nnopqrstuvwxyz\n1234567890\0"; wchar_t* test_text = L" \n "; unsigned int n; for (n = 0; n < wcslen(test_text); n++) { // Console_append(self, test_text[n]); Console_insert(self, test_text[n]); } self->cursor = self->head; return self; }
int main( int argc, char** argv ) { FT_Library library; FT_Face face; FT_GlyphSlot slot; FT_Matrix matrix; /* transformation matrix */ FT_Vector pen; /* untransformed origin */ FT_Error error; char* filename; // char* text; double angle; int target_height; int n, num_chars; wchar_t *chinese_str = L"ол╣Щ1g"; unsigned int *p = (unsigned int *)chinese_str; int i; printf("Uniocde: \n"); for (i = 0; i < wcslen(chinese_str); i++) { printf("0x%x ", p[i]); } printf("\n"); // return 0; if ( argc != 2 ) { fprintf ( stderr, "usage: %s font\n", argv[0] ); exit( 1 ); } filename = argv[1]; /* first argument */ // text = argv[2]; /* second argument */ num_chars = wcslen(chinese_str); angle = ( 0.0 / 360 ) * 3.14159 * 2; /* use 0 degrees */ target_height = HEIGHT; error = FT_Init_FreeType( &library ); /* initialize library */ /* error handling omitted */ error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */ /* error handling omitted */ /* use 20pt at 100dpi */ error = FT_Set_Char_Size( face, 20 * 64, 0, 100, 0 ); /* set character size */ /* error handling omitted */ slot = face->glyph; /* set up matrix */ matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L ); matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L ); matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L ); matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L ); /* the pen position in 26.6 cartesian space coordinates; */ /* start at (0,40) relative to the upper left corner */ pen.x = 0 * 64; pen.y = ( target_height - 40 ) * 64; for ( n = 0; n < num_chars; n++ ) { /* set transformation */ FT_Set_Transform( face, &matrix, &pen ); /* load glyph image into the slot (erase previous one) */ error = FT_Load_Char( face, chinese_str[n], FT_LOAD_RENDER ); if ( error ) continue; /* ignore errors */ /* now, draw to our target surface (convert position) */ draw_bitmap( &slot->bitmap, slot->bitmap_left, target_height - slot->bitmap_top ); /* increment pen position */ pen.x += slot->advance.x; pen.y += slot->advance.y; } show_image(); FT_Done_Face ( face ); FT_Done_FreeType( library ); return 0; }
void DemoEntityManager::CreateOpenGlFont() { FT_Library library; FT_Error error = FT_Init_FreeType (&library); if ( !error ) { char fileName[2048]; //GetWorkingFileName ("arial.ttf", fileName); //GetWorkingFileName ("calibri.ttf", fileName); GetWorkingFileName ("courbd.ttf", fileName); FT_Face face[96]; int withInPixels = 12; int heightInPixels = 16; int width = 0; int height = 0; for (int ch = 0; ch < 96; ch ++) { // Load The Glyph For Our Character. error = FT_New_Face( library, fileName, 0, &face[ch] ); dAssert (!error); FT_Face bitmap = face[ch]; error = FT_Set_Char_Size(bitmap, withInPixels * 64, heightInPixels * 64, 96, 96); dAssert (!error); FT_UInt index = FT_Get_Char_Index( face[ch], ch + ' '); //FT_UInt index = FT_Get_Char_Index (bitmap, 'A'); error = FT_Load_Glyph (bitmap, index, FT_LOAD_DEFAULT ); dAssert (!error); error = FT_Render_Glyph (bitmap->glyph, FT_RENDER_MODE_NORMAL); dAssert (!error); const FT_Glyph_Metrics& metrics = bitmap->glyph->metrics; int w = metrics.width / 64; int h = metrics.height / 64; width += w; height = (height > h) ? height : h; } int imageWidth = TwosPower (width); int imageHeight = TwosPower (height); char* const image = new char[2 * imageWidth * imageHeight]; memset (image, 0, 2 * imageWidth * imageHeight); int maxWidth = 0; int imageBase = 0; for (int ch = 0; ch < 96; ch ++) { FT_Face bitmap = face[ch]; FT_GlyphSlot slot = bitmap->glyph; const FT_Glyph_Metrics& metrics = slot->metrics; int w = metrics.width / 64; int h = metrics.height / 64; maxWidth = (w > maxWidth) ? w : maxWidth; if (w) { const unsigned char* const buffer = slot->bitmap.buffer; int pitch = slot->bitmap.pitch; int posit = imageBase; for (int j = 0; j < h; j ++) { for (int i = 0; i < w; i ++) { int color = buffer[j * pitch + i]; image[posit + i * 2 + 0] = color; image[posit + i * 2 + 1] = color; } posit += imageWidth * 2; } imageBase += w * 2; } } // make th open gl display list here m_fontImage = LoadImage("fontTexture", image, imageWidth, imageHeight, m_luminace); m_font = glGenLists(96); glBindTexture(GL_TEXTURE_2D, m_fontImage); imageBase = 0; for (int ch = 0; ch < 96; ch ++) { FT_Face bitmap = face[ch]; FT_GlyphSlot slot = bitmap->glyph; const FT_Glyph_Metrics& metrics = slot->metrics; glNewList(m_font + ch, GL_COMPILE); glPushMatrix(); // glTranslatef(slot->bitmap_left, 64 - slot->bitmap_top, 0); glTranslatef(slot->bitmap_left, - slot->bitmap_top, 0); dFloat w = dFloat (metrics.width / 64); dFloat h = dFloat (metrics.height / 64); if (w) { dFloat u0 = dFloat (imageBase) / imageWidth; dFloat u1 = dFloat (imageBase + w - 1.0f) / imageWidth; dFloat v0 = 0.0f; dFloat v1 = (h - 1.0f) / imageHeight; glBegin(GL_QUADS); glTexCoord2d (u0, v0); glVertex2i(0, 0); glTexCoord2d (u0, v1); glVertex2i(0, h - 1); glTexCoord2d (u1, v1); glVertex2i (w - 1, h - 1); glTexCoord2d (u1, v0); glVertex2i (w - 1, 0); glEnd(); imageBase += w; } glPopMatrix(); //glTranslatef(maxWidth, 0, 0); glTranslatef(metrics.horiAdvance / 64, 0, 0); glEndList(); FT_Done_Face(bitmap); } delete[] image; // destroy the free type library FT_Done_FreeType (library); } }
//------------------------------------------------------------------ void ofTrueTypeFont::loadFont(string filename, int fontsize, bool _bAntiAliased, bool _bFullCharacterSet, bool makeContours, float simplifyAmt){ bMakeContours = makeContours; //------------------------------------------------ if (bLoadedOk == true){ // we've already been loaded, try to clean up : unloadTextures(); } //------------------------------------------------ filename = ofToDataPath(filename); bLoadedOk = false; bAntiAlised = _bAntiAliased; bFullCharacterSet = _bFullCharacterSet; fontSize = fontsize; //--------------- load the library and typeface FT_Library library; if (FT_Init_FreeType( &library )){ ofLog(OF_LOG_ERROR," PROBLEM WITH FT lib"); return; } FT_Face face; if (FT_New_Face( library, filename.c_str(), 0, &face )) { return; } FT_Set_Char_Size( face, fontsize << 6, fontsize << 6, 96, 96); lineHeight = fontsize * 1.43f; //------------------------------------------------------ //kerning would be great to support: //ofLog(OF_LOG_NOTICE,"FT_HAS_KERNING ? %i", FT_HAS_KERNING(face)); //------------------------------------------------------ nCharacters = bFullCharacterSet ? 256 : 128 - NUM_CHARACTER_TO_START; //--------------- initialize character info and textures cps.resize(nCharacters); if(bMakeContours){ charOutlines.clear(); charOutlines.assign(nCharacters, ofTTFCharacter()); } vector<ofPixels> expanded_data(nCharacters); long areaSum=0; //--------------------- load each char ----------------------- for (int i = 0 ; i < nCharacters; i++){ //------------------------------------------ anti aliased or not: if(FT_Load_Glyph( face, FT_Get_Char_Index( face, (unsigned char)(i+NUM_CHARACTER_TO_START) ), FT_LOAD_DEFAULT )){ ofLog(OF_LOG_ERROR,"error with FT_Load_Glyph %i", i); } if (bAntiAlised == true) FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); else FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO); //------------------------------------------ FT_Bitmap& bitmap= face->glyph->bitmap; // prepare the texture: /*int width = ofNextPow2( bitmap.width + border*2 ); int height = ofNextPow2( bitmap.rows + border*2 ); // ------------------------- this is fixing a bug with small type // ------------------------- appearantly, opengl has trouble with // ------------------------- width or height textures of 1, so we // ------------------------- we just set it to 2... if (width == 1) width = 2; if (height == 1) height = 2;*/ if(bMakeContours){ if( printVectorInfo )printf("\n\ncharacter %c: \n", char( i+NUM_CHARACTER_TO_START ) ); //int character = i + NUM_CHARACTER_TO_START; charOutlines[i] = makeContoursForCharacter( face ); if(simplifyAmt>0) charOutlines[i].simplify(simplifyAmt); charOutlines[i].getTessellation(); } // ------------------------- // info about the character: cps[i].character = i; cps[i].height = face->glyph->bitmap_top; cps[i].width = face->glyph->bitmap.width; cps[i].setWidth = face->glyph->advance.x >> 6; cps[i].topExtent = face->glyph->bitmap.rows; cps[i].leftExtent = face->glyph->bitmap_left; int width = cps[i].width; int height = bitmap.rows; cps[i].tW = width; cps[i].tH = height; GLint fheight = cps[i].height; GLint bwidth = cps[i].width; GLint top = cps[i].topExtent - cps[i].height; GLint lextent = cps[i].leftExtent; GLfloat corr, stretch; //this accounts for the fact that we are showing 2*visibleBorder extra pixels //so we make the size of each char that many pixels bigger stretch = 0;//(float)(visibleBorder * 2); corr = (float)(( (fontSize - fheight) + top) - fontSize); cps[i].x1 = lextent + bwidth + stretch; cps[i].y1 = fheight + corr + stretch; cps[i].x2 = (float) lextent; cps[i].y2 = -top + corr; // Allocate Memory For The Texture Data. expanded_data[i].allocate(width, height, 2); //-------------------------------- clear data: expanded_data[i].set(0,255); // every luminance pixel = 255 expanded_data[i].set(1,0); if (bAntiAlised == true){ ofPixels bitmapPixels; bitmapPixels.setFromExternalPixels(bitmap.buffer,bitmap.width,bitmap.rows,1); expanded_data[i].setChannel(1,bitmapPixels); } else { //----------------------------------- // true type packs monochrome info in a // 1-bit format, hella funky // here we unpack it: unsigned char *src = bitmap.buffer; for(int j=0; j <bitmap.rows;j++) { unsigned char b=0; unsigned char *bptr = src; for(int k=0; k < bitmap.width ; k++){ expanded_data[i][2*(k+j*width)] = 255; if (k%8==0){ b = (*bptr++); } expanded_data[i][2*(k+j*width) + 1] = b&0x80 ? 255 : 0; b <<= 1; } src += bitmap.pitch; } //----------------------------------- } areaSum += (cps[i].width+border*2)*(cps[i].height+border*2); } vector<charProps> sortedCopy = cps; sort(sortedCopy.begin(),sortedCopy.end(),&compare_cps); // pack in a texture, algorithm to calculate min w/h from // http://upcommons.upc.edu/pfc/bitstream/2099.1/7720/1/TesiMasterJonas.pdf //cout << areaSum << endl; bool packed = false; float alpha = logf(areaSum)*1.44269; int w; int h; while(!packed){ w = pow(2,floor((alpha/2.f) + 0.5)); // there doesn't seem to be a round in cmath for windows. //w = pow(2,round(alpha/2.f)); h = w;//pow(2,round(alpha - round(alpha/2.f))); int x=0; int y=0; int maxRowHeight = sortedCopy[0].tH + border*2; for(int i=0;i<(int)cps.size();i++){ if(x+sortedCopy[i].tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = sortedCopy[i].tH + border*2; if(y + maxRowHeight > h){ alpha++; break; } } x+= sortedCopy[i].tW + border*2; if(i==(int)cps.size()-1) packed = true; } } ofPixels atlasPixels; atlasPixels.allocate(w,h,2); atlasPixels.set(0,255); atlasPixels.set(1,0); int x=0; int y=0; int maxRowHeight = sortedCopy[0].tH + border*2; for(int i=0;i<(int)cps.size();i++){ ofPixels & charPixels = expanded_data[sortedCopy[i].character]; if(x+sortedCopy[i].tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = sortedCopy[i].tH + border*2; } cps[sortedCopy[i].character].t2 = float(x + border)/float(w); cps[sortedCopy[i].character].v2 = float(y + border)/float(h); cps[sortedCopy[i].character].t1 = float(cps[sortedCopy[i].character].tW + x + border)/float(w); cps[sortedCopy[i].character].v1 = float(cps[sortedCopy[i].character].tH + y + border)/float(h); charPixels.pasteInto(atlasPixels,x+border,y+border); x+= sortedCopy[i].tW + border*2; } texAtlas.allocate(atlasPixels.getWidth(),atlasPixels.getHeight(),GL_LUMINANCE_ALPHA,false); if(bAntiAlised && fontsize>14){ texAtlas.setTextureMinMagFilter(GL_LINEAR,GL_LINEAR); }else{ texAtlas.setTextureMinMagFilter(GL_NEAREST,GL_NEAREST); } texAtlas.loadData(atlasPixels.getPixels(),atlasPixels.getWidth(),atlasPixels.getHeight(),GL_LUMINANCE_ALPHA); // ------------- close the library and typeface FT_Done_Face(face); FT_Done_FreeType(library); bLoadedOk = true; }
int main(int argc, char** argv) { FT_Error error; FT_Library library; FT_Face face; FT_Glyph_Metrics* m; FT_Outline* o; FT_Int major, minor, patch; int i, j, font_size, no_hinting; if (argc != 4) { usage(argv); return 1; } font_size = atoi(argv[1]); if (font_size <= 0) { fprintf(stderr, "invalid font_size\n"); usage(argv); return 1; } if (!strcmp(argv[3], "with_hinting")) { no_hinting = 0; } else if (!strcmp(argv[3], "sans_hinting")) { no_hinting = 1; } else { fprintf(stderr, "neither \"with_hinting\" nor \"sans_hinting\"\n"); usage(argv); return 1; }; error = FT_Init_FreeType(&library); if (error) { fprintf(stderr, "FT_Init_FreeType: error #%d\n", error); return 1; } FT_Library_Version(library, &major, &minor, &patch); printf("freetype version %d.%d.%d\n", major, minor, patch); error = FT_New_Face(library, argv[2], 0, &face); if (error) { fprintf(stderr, "FT_New_Face: error #%d\n", error); return 1; } error = FT_Set_Char_Size(face, 0, font_size*64, 0, 0); if (error) { fprintf(stderr, "FT_Set_Char_Size: error #%d\n", error); return 1; } for (i = 0; i < face->num_glyphs; i++) { error = FT_Load_Glyph(face, i, no_hinting ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT); if (error) { fprintf(stderr, "FT_Load_Glyph: glyph %d: error #%d\n", i, error); return 1; } if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) { fprintf(stderr, "glyph format for glyph %d is not FT_GLYPH_FORMAT_OUTLINE\n", i); return 1; } m = &face->glyph->metrics; /* Print what Go calls the AdvanceWidth, and then: XMin, YMin, XMax, YMax. */ printf("%ld %ld %ld %ld %ld;", m->horiAdvance, m->horiBearingX, m->horiBearingY - m->height, m->horiBearingX + m->width, m->horiBearingY); /* Print the glyph points. */ o = &face->glyph->outline; for (j = 0; j < o->n_points; j++) { if (j != 0) { printf(", "); } printf("%ld %ld %d", o->points[j].x, o->points[j].y, o->tags[j] & 0x01); } printf("\n"); } return 0; }
/* ------------------------------------------------------------------------- */ int texture_font_load_face( FT_Library * library, const char * filename, const float size, FT_Face * face ) { size_t hres = 64; FT_Error error; FT_Matrix matrix = { (int)((1.0/hres) * 0x10000L), (int)((0.0) * 0x10000L), (int)((0.0) * 0x10000L), (int)((1.0) * 0x10000L) }; /* Initialize library */ error = FT_Init_FreeType( library ); if( error ) { fprintf(stderr, "FT_Error (0x%02x) : %s\n", FT_Errors[error].code, FT_Errors[error].message); return 0; } /* Load face */ error = FT_New_Face( *library, filename, 0, face ); if( error ) { fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", __LINE__, FT_Errors[error].code, FT_Errors[error].message); FT_Done_FreeType( *library ); return 0; } /* Select charmap */ error = FT_Select_Charmap( *face, FT_ENCODING_UNICODE ); if( error ) { fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", __LINE__, FT_Errors[error].code, FT_Errors[error].message); FT_Done_Face( *face ); FT_Done_FreeType( *library ); return 0; } /* Set char size */ error = FT_Set_Char_Size( *face, (int)(size*64), 0, 72*hres, 72 ); /* error = FT_Set_Char_Size( *face, size*64, 0, 72, 72 ); */ if( error ) { fprintf(stderr, "FT_Error (line %d, code 0x%02x) : %s\n", __LINE__, FT_Errors[error].code, FT_Errors[error].message); FT_Done_Face( *face ); FT_Done_FreeType( *library ); return 0; } /* Set transform matrix */ FT_Set_Transform( *face, &matrix, NULL ); return 1; }
void font_init() { if (FT_Init_FreeType(&library)) { printf("font init failed"); } }
void XeTeXFontInst::initialize(const char* pathname, int index, int &status) { TT_Postscript *postTable; TT_OS2* os2Table; FT_Error error; hb_face_t *hbFace; if (!gFreeTypeLibrary) { error = FT_Init_FreeType(&gFreeTypeLibrary); if (error) { fprintf(stderr, "FreeType initialization failed! (%d)\n", error); exit(1); } } error = FT_New_Face(gFreeTypeLibrary, pathname, index, &m_ftFace); if (error) { status = 1; return; } if (!FT_IS_SCALABLE(m_ftFace)) { status = 1; return; } /* for non-sfnt-packaged fonts (presumably Type 1), see if there is an AFM file we can attach */ if (index == 0 && !FT_IS_SFNT(m_ftFace)) { char* afm = xstrdup (xbasename (pathname)); char* p = strrchr (afm, '.'); if (p != NULL && strlen(p) == 4 && tolower(*(p+1)) == 'p' && tolower(*(p+2)) == 'f') strcpy(p, ".afm"); char *fullafm = kpse_find_file (afm, kpse_afm_format, 0); free (afm); if (fullafm) { FT_Attach_File(m_ftFace, fullafm); free (fullafm); } } m_filename = xstrdup(pathname); m_index = index; m_unitsPerEM = m_ftFace->units_per_EM; m_ascent = unitsToPoints(m_ftFace->ascender); m_descent = unitsToPoints(m_ftFace->descender); postTable = (TT_Postscript *) getFontTable(ft_sfnt_post); if (postTable != NULL) { m_italicAngle = Fix2D(postTable->italicAngle); } os2Table = (TT_OS2*) getFontTable(ft_sfnt_os2); if (os2Table) { m_capHeight = unitsToPoints(os2Table->sCapHeight); m_xHeight = unitsToPoints(os2Table->sxHeight); } // Set up HarfBuzz font hbFace = hb_face_create_for_tables(_get_table, m_ftFace, NULL); hb_face_set_index(hbFace, index); hb_face_set_upem(hbFace, m_unitsPerEM); m_hbFont = hb_font_create(hbFace); hb_face_destroy(hbFace); if (hbFontFuncs == NULL) hbFontFuncs = _get_font_funcs(); hb_font_set_funcs(m_hbFont, hbFontFuncs, m_ftFace, NULL); hb_font_set_scale(m_hbFont, m_unitsPerEM, m_unitsPerEM); // We don’t want device tables adjustments hb_font_set_ppem(m_hbFont, 0, 0); return; }