fut*_*lib 6 c++ io zip android freetype2
我正在尝试使用libzip和FreeType直接从ZIP存档加载TTF文件.
特别是,我正在使用FT_Open_Face函数,该函数可以读取自定义读取/关闭函数(ft_zip_read和ft_zip_close).但是,虽然文件显然已完全读取,但FT_Open_Face返回FT_Err_Unknown_File_Format.直接从磁盘打开相同的文件工作正常.
我真的不知道如何调试这个,有人可以帮忙吗?
我现在唯一能想到的问题就是我的ft_zip_read功能不支持搜索,文档说:
可以调用此函数以执行"计数"为0的搜索或跳过操作.非零返回值则表示错误.
它确实被调用了0次,但我看不出用libzip进行搜索的任何方法.
unsigned long ft_zip_read(FT_Stream stream, unsigned long offset,
unsigned char* buffer, unsigned long count)
{
zip_file* file = static_cast<zip_file*>(stream->descriptor.pointer);
return zip_fread(file, buffer + offset, count);
}
void ft_zip_close(FT_Stream stream)
{
zip_file* file = static_cast<zip_file*>(stream->descriptor.pointer);
zip_fclose(file);
}
FT_Face load_zipped_face(const std::string& name, unsigned int size,
const std::string& zip_path)
{
FT_Library library;
FT_Error error = FT_Init_FreeType(&library);
if (error)
throw freetype_error_string("Failed to initialise FreeType", error);
int zip_error;
zip* zip = zip_open(zip_path.c_str(), 0, &zip_error);
if (!zip) {
std::ostringstream message_stream;
message_stream << "Error loading ZIP (" << zip_path << "): "
<< zip_error;
throw message_stream.str();
}
std::string face_path = name + ".ttf";
struct zip_stat stat;
if (zip_stat(zip, face_path.c_str(), 0, &stat))
throw std::string("zip_stat failed");
zip_file* file = zip_fopen(zip, face_path.c_str(), 0);
if (file == 0)
throw face_path + ": " + strerror(errno);
FT_StreamDesc descriptor;
descriptor.pointer = file;
FT_StreamRec* stream = new FT_StreamRec;
stream->base = 0;
stream->size = stat.size;
stream->descriptor = descriptor;
stream->read = &ft_zip_read;
stream->close = &ft_zip_close;
FT_Open_Args open_args;
open_args.flags = FT_OPEN_STREAM;
open_args.stream = stream;
FT_Face face;
error = FT_Open_Face(library, &open_args, 0, &face);
zip_close(zip);
if (error == FT_Err_Unknown_File_Format)
throw std::string("Unsupported format");
else if (error)
throw freetype_error_string("Unknown error loading font", error);
error = FT_Set_Pixel_Sizes(face, 0, size);
if (error)
throw freetype_error_string("Unable to set pixel sizes", error);
return face;
}
Run Code Online (Sandbox Code Playgroud)
为了能够在压缩数据流中查找,您需要解压缩流,直到您想要查找的点(存在一些例外,例如具有重置标记和索引的流,只需从前一个标记开始解压缩)。如果经常这样做的话,效率很低(更不用说您需要自己编写代码)。
现在想想,您不想将整个面加载到内存中并为字体文件提供自定义 IO 的唯一原因是它太大而无法保留在内存中;因此,FT 的流 IO 接口必须进行查找。
如果文件足够小:将其全部读入内存并用于FT_New_Memory_Face从内存加载面部。
如果文件太大,以至于您不希望一次将整个脸部存入内存,请将字体文件提取到临时文件并从中读取。(使用 windows/unix/cstdio 临时文件 API 来获得性能良好的临时文件)
如果以上都不适合您,那么您可以在 libzip 之上实现您自己的缓存和可查找 zip 流,并将其传递给 FT。这可能很麻烦并且涉及一些工作,所以我个人会选择另外两个之一:)
| 归档时间: |
|
| 查看次数: |
762 次 |
| 最近记录: |