1// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
2// Copyright 2012, SIL International, All rights reserved.
3
4#include <cstring>
5#include "inc/FileFace.h"
6
7
8#ifndef GRAPHITE2_NFILEFACE
9
10using namespace graphite2;
11
12FileFace::FileFace(const char *filename)
13: _file(fopen(filename, "rb")),
14 _file_len(0),
15 _header_tbl(NULL),
16 _table_dir(NULL)
17{
18 if (!_file) return;
19
20 if (fseek(_file, 0, SEEK_END)) return;
21 _file_len = ftell(_file);
22 if (fseek(_file, 0, SEEK_SET)) return;
23
24 size_t tbl_offset, tbl_len;
25
26 // Get the header.
27 if (!TtfUtil::GetHeaderInfo(tbl_offset, tbl_len)) return;
28 if (fseek(_file, long(tbl_offset), SEEK_SET)) return;
29 _header_tbl = (TtfUtil::Sfnt::OffsetSubTable*)gralloc<char>(tbl_len);
30 if (_header_tbl)
31 {
32 if (fread(_header_tbl, 1, tbl_len, _file) != tbl_len) return;
33 if (!TtfUtil::CheckHeader(_header_tbl)) return;
34 }
35
36 // Get the table directory
37 if (!TtfUtil::GetTableDirInfo(_header_tbl, tbl_offset, tbl_len)) return;
38 _table_dir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(tbl_len);
39 if (fseek(_file, long(tbl_offset), SEEK_SET)) return;
40 if (_table_dir && fread(_table_dir, 1, tbl_len, _file) != tbl_len)
41 {
42 free(_table_dir);
43 _table_dir = NULL;
44 }
45 return;
46}
47
48FileFace::~FileFace()
49{
50 free(_table_dir);
51 free(_header_tbl);
52 if (_file)
53 fclose(_file);
54}
55
56
57const void *FileFace::get_table_fn(const void* appFaceHandle, unsigned int name, size_t *len)
58{
59 if (appFaceHandle == 0) return 0;
60 const FileFace & file_face = *static_cast<const FileFace *>(appFaceHandle);
61
62 void *tbl;
63 size_t tbl_offset, tbl_len;
64 if (!TtfUtil::GetTableInfo(name, file_face._header_tbl, file_face._table_dir, tbl_offset, tbl_len))
65 return 0;
66
67 if (tbl_offset > file_face._file_len || tbl_len > file_face._file_len - tbl_offset
68 || fseek(file_face._file, long(tbl_offset), SEEK_SET) != 0)
69 return 0;
70
71 tbl = malloc(tbl_len);
72 if (!tbl || fread(tbl, 1, tbl_len, file_face._file) != tbl_len)
73 {
74 free(tbl);
75 return 0;
76 }
77
78 if (len) *len = tbl_len;
79 return tbl;
80}
81
82void FileFace::rel_table_fn(const void* appFaceHandle, const void *table_buffer)
83{
84 if (appFaceHandle == 0) return;
85
86 free(const_cast<void *>(table_buffer));
87}
88
89const gr_face_ops FileFace::ops = { sizeof FileFace::ops, &FileFace::get_table_fn, &FileFace::rel_table_fn };
90
91
92#endif //!GRAPHITE2_NFILEFACE
93