Faster font i/o backported to 2.3.x - refs #2282

This commit is contained in:
Dane Springmeyer 2014-06-24 19:46:46 -07:00
parent a1cab08d77
commit bdd800b6fc

View file

@ -90,16 +90,14 @@ bool freetype_engine::is_font_file(std::string const& file_name)
} }
unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
if (count <= 0) return count; if (count <= 0) return 0;
std::ifstream * file = static_cast<std::ifstream *>(stream->descriptor.pointer); FILE * file = static_cast<FILE *>(stream->descriptor.pointer);
file->seekg(offset, std::ios::beg); std::fseek (file , offset , SEEK_SET);
file->read((char*)buffer, count); return std::fread ((char*)buffer, 1, count, file);
return file->gcount();
} }
void ft_close_cb(FT_Stream stream) { void ft_close_cb(FT_Stream stream) {
std::ifstream * file = static_cast<std::ifstream *>(stream->descriptor.pointer); std::fclose (static_cast<std::FILE *>(stream->descriptor.pointer));
file->close();
} }
bool freetype_engine::register_font(std::string const& file_name) bool freetype_engine::register_font(std::string const& file_name)
@ -109,13 +107,11 @@ bool freetype_engine::register_font(std::string const& file_name)
#endif #endif
#ifdef _WINDOWS #ifdef _WINDOWS
std::ifstream file(mapnik::utf8_to_utf16(file_name) , std::ios::binary); FILE * file = _wfopen(mapnik::utf8_to_utf16(file_name).c_str(), L"rb");
#else #else
std::ifstream file(file_name.c_str() , std::ios::binary); FILE * file = std::fopen(file_name.c_str(),"rb");
#endif #endif
if (!file.good()) { if (file == NULL) return false;
return false;
}
FT_Library library = 0; FT_Library library = 0;
FT_Error error = FT_Init_FreeType(&library); FT_Error error = FT_Init_FreeType(&library);
@ -129,16 +125,13 @@ bool freetype_engine::register_font(std::string const& file_name)
FT_StreamRec streamRec; FT_StreamRec streamRec;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
memset(&streamRec, 0, sizeof(streamRec)); memset(&streamRec, 0, sizeof(streamRec));
std::streampos beg = file.tellg(); fseek(file, 0, SEEK_END);
file.seekg (0, std::ios::end); std::size_t file_size = std::ftell(file);
std::streampos end = file.tellg(); fseek(file, 0, SEEK_SET);
std::size_t file_size = end - beg;
file.seekg (0, std::ios::beg);
streamRec.base = 0; streamRec.base = 0;
streamRec.pos = 0; streamRec.pos = 0;
streamRec.size = file_size; streamRec.size = file_size;
streamRec.descriptor.pointer = &file; streamRec.descriptor.pointer = file;
streamRec.read = ft_read_cb; streamRec.read = ft_read_cb;
streamRec.close = ft_close_cb; streamRec.close = ft_close_cb;
args.flags = FT_OPEN_STREAM; args.flags = FT_OPEN_STREAM;
@ -183,9 +176,8 @@ bool freetype_engine::register_font(std::string const& file_name)
MAPNIK_LOG_ERROR(font_engine_freetype) << "register_font: " << s.str(); MAPNIK_LOG_ERROR(font_engine_freetype) << "register_font: " << s.str();
} }
if (face) FT_Done_Face(face);
} }
if (face)
FT_Done_Face(face);
if (library) if (library)
FT_Done_FreeType(library); FT_Done_FreeType(library);
return success; return success;
@ -300,22 +292,33 @@ face_ptr freetype_engine::create_face(std::string const& family_name)
#ifdef MAPNIK_THREADSAFE #ifdef MAPNIK_THREADSAFE
mutex::scoped_lock lock(mutex_); mutex::scoped_lock lock(mutex_);
#endif #endif
std::ifstream is(itr->second.second.c_str() , std::ios::binary); #ifdef _WINDOWS
std::string buffer((std::istreambuf_iterator<char>(is)), FILE * file = _wfopen(mapnik::utf8_to_utf16(itr->second.second).c_str(), L"rb");
std::istreambuf_iterator<char>()); #else
std::pair<std::map<std::string,std::string>::iterator,bool> result FILE * file = std::fopen(itr->second.second.c_str(),"rb");
= memory_fonts_.insert(std::make_pair(itr->second.second, buffer)); #endif
if (file != NULL)
FT_Error error = FT_New_Memory_Face (library_,
reinterpret_cast<FT_Byte const*>(result.first->second.c_str()),
static_cast<FT_Long>(buffer.size()),
itr->second.first,
&face);
if (!error) return boost::make_shared<font_face>(face);
else
{ {
// we can't load font, erase it. std::fseek(file, 0, SEEK_END);
memory_fonts_.erase(result.first); std::size_t file_size = std::ftell(file);
std::fseek(file, 0, SEEK_SET);
std::string buffer;
buffer.resize(file_size);
std::fread(&buffer[0], file_size, 1, file);
std::pair<std::map<std::string,std::string>::iterator,bool> result =
memory_fonts_.insert(std::make_pair(itr->second.second, buffer));
FT_Error error = FT_New_Memory_Face (library_,
reinterpret_cast<FT_Byte const*>(result.first->second.c_str()),
static_cast<FT_Long>(buffer.size()),
itr->second.first,
&face);
std::fclose(file);
if (!error) return boost::make_shared<font_face>(face);
else
{
// we can't load font, erase it.
memory_fonts_.erase(result.first);
}
} }
} }
} }