| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | #include "FreeTypeLibrary.h" |
|---|
| 15 | #include <osg/Notify> |
|---|
| 16 | |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | #ifdef PRINT_OUT_FONT_DETAILS |
|---|
| 20 | #include <freetype/ftsnames.h> |
|---|
| 21 | #endif |
|---|
| 22 | |
|---|
| 23 | #include FT_TRUETYPE_IDS_H |
|---|
| 24 | |
|---|
| 25 | FreeTypeLibrary::FreeTypeLibrary() |
|---|
| 26 | { |
|---|
| 27 | OSG_INFO << "FreeTypeLibrary::FreeTypeLibrary()" << std::endl; |
|---|
| 28 | FT_Error error = FT_Init_FreeType( &_ftlibrary ); |
|---|
| 29 | if (error) |
|---|
| 30 | { |
|---|
| 31 | OSG_WARN<<"Warning: an error occurred during FT_Init_FreeType(..) initialisation, error code = "<<std::hex<<error<<std::dec<<std::endl; |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | FreeTypeLibrary::~FreeTypeLibrary() |
|---|
| 37 | { |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | while(!_fontImplementationSet.empty()) |
|---|
| 44 | { |
|---|
| 45 | FreeTypeFont* fontImplementation = *_fontImplementationSet.begin(); |
|---|
| 46 | _fontImplementationSet.erase(_fontImplementationSet.begin()); |
|---|
| 47 | osgText::Font* font = fontImplementation->_facade; |
|---|
| 48 | if (font) font->setImplementation(0); |
|---|
| 49 | else fontImplementation->_facade = 0; |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | FT_Done_FreeType( _ftlibrary); |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | FreeTypeLibrary* FreeTypeLibrary::instance() |
|---|
| 56 | { |
|---|
| 57 | static osg::ref_ptr<FreeTypeLibrary> s_library = new FreeTypeLibrary; |
|---|
| 58 | return s_library.get(); |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | bool FreeTypeLibrary::getFace(const std::string& fontfile,unsigned int index, FT_Face & face) |
|---|
| 62 | { |
|---|
| 63 | OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex()); |
|---|
| 64 | |
|---|
| 65 | FT_Error error = FT_New_Face( _ftlibrary, fontfile.c_str(), index, &face ); |
|---|
| 66 | if (error == FT_Err_Unknown_File_Format) |
|---|
| 67 | { |
|---|
| 68 | OSG_WARN<<" .... the font file could be opened and read, but it appears"<<std::endl; |
|---|
| 69 | OSG_WARN<<" .... that its font format is unsupported"<<std::endl; |
|---|
| 70 | return false; |
|---|
| 71 | } |
|---|
| 72 | else if (error) |
|---|
| 73 | { |
|---|
| 74 | OSG_WARN<<" .... another error code means that the font file could not"<<std::endl; |
|---|
| 75 | OSG_WARN<<" .... be opened, read or simply that it is broken.."<<std::endl; |
|---|
| 76 | return false; |
|---|
| 77 | } |
|---|
| 78 | |
|---|
| 79 | #ifdef PRINT_OUT_FONT_DETAILS |
|---|
| 80 | |
|---|
| 81 | OSG_NOTICE<<"Face"<<face<<std::endl; |
|---|
| 82 | unsigned int count = FT_Get_Sfnt_Name_Count(face); |
|---|
| 83 | for(unsigned int i=0; i<count; ++i) |
|---|
| 84 | { |
|---|
| 85 | FT_SfntName names; |
|---|
| 86 | FT_Error error = FT_Get_Sfnt_Name(face, i, &names); |
|---|
| 87 | |
|---|
| 88 | std::string name((char*)names.string, (char*)names.string + names.string_len); |
|---|
| 89 | |
|---|
| 90 | OSG_NOTICE<<"names "<<name<<std::endl; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | OSG_NOTICE<<std::endl; |
|---|
| 94 | #endif |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | |
|---|
| 98 | |
|---|
| 99 | verifyCharacterMap(face); |
|---|
| 100 | |
|---|
| 101 | return true; |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | FT_Byte* FreeTypeLibrary::getFace(std::istream& fontstream, unsigned int index, FT_Face & face) |
|---|
| 105 | { |
|---|
| 106 | OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex()); |
|---|
| 107 | |
|---|
| 108 | FT_Open_Args args; |
|---|
| 109 | |
|---|
| 110 | std::streampos start = fontstream.tellg(); |
|---|
| 111 | fontstream.seekg(0, std::ios::end); |
|---|
| 112 | std::streampos end = fontstream.tellg(); |
|---|
| 113 | fontstream.seekg(start, std::ios::beg); |
|---|
| 114 | std::streampos length = end - start; |
|---|
| 115 | |
|---|
| 116 | |
|---|
| 117 | FT_Byte *buffer = new FT_Byte[length]; |
|---|
| 118 | fontstream.read(reinterpret_cast<char*>(buffer), length); |
|---|
| 119 | if (!fontstream || (static_cast<std::streampos>(fontstream.gcount()) != length)) |
|---|
| 120 | { |
|---|
| 121 | OSG_WARN<<" .... the font file could not be read from its stream"<<std::endl; |
|---|
| 122 | if (buffer) delete [] buffer; |
|---|
| 123 | return 0; |
|---|
| 124 | } |
|---|
| 125 | args.flags = FT_OPEN_MEMORY; |
|---|
| 126 | args.memory_base = buffer; |
|---|
| 127 | args.memory_size = length; |
|---|
| 128 | |
|---|
| 129 | FT_Error error = FT_Open_Face( _ftlibrary, &args, index, &face ); |
|---|
| 130 | |
|---|
| 131 | if (error == FT_Err_Unknown_File_Format) |
|---|
| 132 | { |
|---|
| 133 | OSG_WARN<<" .... the font file could be opened and read, but it appears"<<std::endl; |
|---|
| 134 | OSG_WARN<<" .... that its font format is unsupported"<<std::endl; |
|---|
| 135 | return 0; |
|---|
| 136 | } |
|---|
| 137 | else if (error) |
|---|
| 138 | { |
|---|
| 139 | OSG_WARN<<" .... another error code means that the font file could not"<<std::endl; |
|---|
| 140 | OSG_WARN<<" .... be opened, read or simply that it is broken..."<<std::endl; |
|---|
| 141 | return 0; |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | verifyCharacterMap(face); |
|---|
| 148 | |
|---|
| 149 | return buffer; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | |
|---|
| 153 | osgText::Font* FreeTypeLibrary::getFont(const std::string& fontfile, unsigned int index, unsigned int flags) |
|---|
| 154 | { |
|---|
| 155 | FT_Face face; |
|---|
| 156 | if (getFace(fontfile, index, face) == false) return (0); |
|---|
| 157 | |
|---|
| 158 | OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex()); |
|---|
| 159 | |
|---|
| 160 | FreeTypeFont* fontImp = new FreeTypeFont(fontfile,face,flags); |
|---|
| 161 | osgText::Font* font = new osgText::Font(fontImp); |
|---|
| 162 | |
|---|
| 163 | _fontImplementationSet.insert(fontImp); |
|---|
| 164 | |
|---|
| 165 | return font; |
|---|
| 166 | } |
|---|
| 167 | osgText::Font* FreeTypeLibrary::getFont(std::istream& fontstream, unsigned int index, unsigned int flags) |
|---|
| 168 | { |
|---|
| 169 | FT_Face face = 0; |
|---|
| 170 | FT_Byte * buffer = getFace(fontstream, index, face); |
|---|
| 171 | if (face == 0) return (0); |
|---|
| 172 | |
|---|
| 173 | |
|---|
| 174 | OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getMutex()); |
|---|
| 175 | |
|---|
| 176 | FreeTypeFont* fontImp = new FreeTypeFont(buffer,face,flags); |
|---|
| 177 | osgText::Font* font = new osgText::Font(fontImp); |
|---|
| 178 | |
|---|
| 179 | _fontImplementationSet.insert(fontImp); |
|---|
| 180 | |
|---|
| 181 | return font; |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | void FreeTypeLibrary::verifyCharacterMap(FT_Face face) |
|---|
| 185 | { |
|---|
| 186 | |
|---|
| 187 | |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | FT_CharMap charmap; |
|---|
| 191 | if (face->charmap == NULL) |
|---|
| 192 | { |
|---|
| 193 | for (int n = 0; n < face->num_charmaps; n++) |
|---|
| 194 | { |
|---|
| 195 | charmap = face->charmaps[n]; |
|---|
| 196 | if (charmap->platform_id == TT_PLATFORM_MICROSOFT) |
|---|
| 197 | { |
|---|
| 198 | FT_Set_Charmap(face, charmap); |
|---|
| 199 | break; |
|---|
| 200 | } |
|---|
| 201 | } |
|---|
| 202 | } |
|---|
| 203 | } |
|---|