|
|
|
@ -3,6 +3,9 @@ |
|
|
|
|
# error "a C++11 compiler is needed" |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include <archive.h> |
|
|
|
|
#include <archive_entry.h> |
|
|
|
|
|
|
|
|
|
#include <assert.h> |
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
@ -45,6 +48,59 @@ using namespace std; |
|
|
|
|
|
|
|
|
|
FT_Global global_ft; |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
archive_read_entry_data( struct archive *ar, vector<FT_Byte> *vw ) |
|
|
|
|
{ |
|
|
|
|
int r; |
|
|
|
|
const FT_Byte *buff; |
|
|
|
|
size_t size; |
|
|
|
|
int64_t offset; |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
r = archive_read_data_block( ar, reinterpret_cast<const void**>(&buff), &size, &offset ); |
|
|
|
|
if (r == ARCHIVE_EOF) |
|
|
|
|
return (ARCHIVE_OK); |
|
|
|
|
if (r != ARCHIVE_OK) |
|
|
|
|
return (r); |
|
|
|
|
vw->insert(vw->end(), buff, buff + size); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static vector<vector<FT_Byte>> |
|
|
|
|
parse_data( const uint8_t* data, |
|
|
|
|
size_t size ) |
|
|
|
|
{ |
|
|
|
|
struct archive_entry *entry; |
|
|
|
|
int r; |
|
|
|
|
vector<vector<FT_Byte>> files; |
|
|
|
|
|
|
|
|
|
unique_ptr<struct archive, decltype ( archive_read_free )*> a( archive_read_new(), archive_read_free ); |
|
|
|
|
archive_read_support_format_tar(a.get()); |
|
|
|
|
|
|
|
|
|
// The need for the const_cast was removed with libarchive be4d4ddcfca77f6e43753156eaa919f4d25ed903
|
|
|
|
|
if (!(r = archive_read_open_memory( a.get(), const_cast<void*>(static_cast<const void*>(data)), size ))) |
|
|
|
|
{ |
|
|
|
|
unique_ptr<struct archive, decltype ( archive_read_close )*> a_open( a.get(), archive_read_close ); |
|
|
|
|
for (;;) { |
|
|
|
|
r = archive_read_next_header( a_open.get(), &entry ); |
|
|
|
|
if (r == ARCHIVE_EOF) |
|
|
|
|
break; |
|
|
|
|
if (r != ARCHIVE_OK) |
|
|
|
|
break; |
|
|
|
|
vector<FT_Byte> entry_data; |
|
|
|
|
r = archive_read_entry_data( a.get(), &entry_data ); |
|
|
|
|
if (r != ARCHIVE_OK) |
|
|
|
|
break; |
|
|
|
|
files.push_back( move( entry_data ) ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (files.size() == 0) |
|
|
|
|
files.emplace_back(data, data + size); |
|
|
|
|
|
|
|
|
|
return files; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
setIntermediateAxis( FT_Face face ) |
|
|
|
@ -85,6 +141,8 @@ using namespace std; |
|
|
|
|
|
|
|
|
|
long size = (long)size_; |
|
|
|
|
|
|
|
|
|
const vector<vector<FT_Byte>>& files = parse_data( data, size ); |
|
|
|
|
|
|
|
|
|
FT_Face face; |
|
|
|
|
FT_Int32 load_flags = FT_LOAD_DEFAULT; |
|
|
|
|
#if 0 |
|
|
|
@ -99,7 +157,7 @@ using namespace std; |
|
|
|
|
// more than a single font.
|
|
|
|
|
|
|
|
|
|
// get number of faces
|
|
|
|
|
if ( FT_New_Memory_Face( library, data, size, -1, &face ) ) |
|
|
|
|
if ( FT_New_Memory_Face( library, files[0].data(), files[0].size(), -1, &face ) ) |
|
|
|
|
return 0; |
|
|
|
|
long num_faces = face->num_faces; |
|
|
|
|
FT_Done_Face( face ); |
|
|
|
@ -111,8 +169,8 @@ using namespace std; |
|
|
|
|
{ |
|
|
|
|
// get number of instances
|
|
|
|
|
if ( FT_New_Memory_Face( library, |
|
|
|
|
data, |
|
|
|
|
size, |
|
|
|
|
files[0].data(), |
|
|
|
|
files[0].size(), |
|
|
|
|
-( face_index + 1 ), |
|
|
|
|
&face ) ) |
|
|
|
|
continue; |
|
|
|
@ -125,12 +183,23 @@ using namespace std; |
|
|
|
|
instance_index++ ) |
|
|
|
|
{ |
|
|
|
|
if ( FT_New_Memory_Face( library, |
|
|
|
|
data, |
|
|
|
|
size, |
|
|
|
|
files[0].data(), |
|
|
|
|
files[0].size(), |
|
|
|
|
( instance_index << 16 ) + face_index, |
|
|
|
|
&face ) ) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
for ( long files_index = 1; |
|
|
|
|
files_index < files.size(); |
|
|
|
|
files_index++) |
|
|
|
|
{ |
|
|
|
|
FT_Open_Args open_args = {}; |
|
|
|
|
open_args.flags = FT_OPEN_MEMORY; |
|
|
|
|
open_args.memory_base = files[files_index].data(); |
|
|
|
|
open_args.memory_size = files[files_index].size(); |
|
|
|
|
FT_Attach_Stream( face, &open_args ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// loop over all bitmap stroke sizes
|
|
|
|
|
// and an arbitrary size for outlines
|
|
|
|
|
for ( long fixed_sizes_index = 0; |
|
|
|
|