1 : /* GRAPHITE2 LICENSING
2 :
3 : Copyright 2010, SIL International
4 : All rights reserved.
5 :
6 : This library is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU Lesser General Public License as published
8 : by the Free Software Foundation; either version 2.1 of License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should also have received a copy of the GNU Lesser General Public
17 : License along with this library in the file named "LICENSE".
18 : If not, write to the Free Software Foundation, 51 Franklin Street,
19 : Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 : internet at http://www.fsf.org/licenses/lgpl.html.
21 :
22 : Alternatively, the contents of this file may be used under the terms of the
23 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 : License, as published by the Free Software Foundation, either version 2
25 : of the License or (at your option) any later version.
26 : */
27 : #include <cstring>
28 : #include "graphite2/Segment.h"
29 : #include "inc/Face.h"
30 : #include "inc/Endian.h"
31 : #include "inc/Segment.h"
32 : #include "inc/CmapCache.h"
33 : #include "inc/NameTable.h"
34 : #include "inc/SegCacheStore.h"
35 :
36 :
37 : using namespace graphite2;
38 :
39 0 : Face::~Face()
40 : {
41 0 : delete m_pGlyphFaceCache;
42 0 : delete m_cmap;
43 0 : delete[] m_silfs;
44 0 : m_pGlyphFaceCache = NULL;
45 0 : m_cmap = NULL;
46 0 : m_silfs = NULL;
47 0 : delete m_pFileFace;
48 0 : delete m_pNames;
49 0 : m_pFileFace = NULL;
50 0 : }
51 :
52 :
53 0 : bool Face::readGlyphs(uint32 faceOptions)
54 : {
55 : GlyphFaceCacheHeader hdr;
56 0 : if (!hdr.initialize(*this, faceOptions & gr_face_dumbRendering)) return false;
57 :
58 0 : m_pGlyphFaceCache = GlyphFaceCache::makeCache(hdr);
59 0 : if (!m_pGlyphFaceCache) return false;
60 :
61 0 : size_t length = 0;
62 0 : const byte * table = getTable(Tag::cmap, &length);
63 0 : if (!table) return false;
64 :
65 0 : if (faceOptions & gr_face_cacheCmap)
66 0 : m_cmap = new CmapCache(table, length);
67 : else
68 0 : m_cmap = new DirectCmap(table, length);
69 :
70 0 : if (!m_cmap || !*m_cmap) return false;
71 :
72 0 : if (faceOptions & gr_face_preloadGlyphs)
73 : {
74 0 : m_pGlyphFaceCache->loadAllGlyphs();
75 0 : nameTable(); // preload the name table along with the glyphs, heh.
76 : }
77 0 : m_upem = TtfUtil::DesignUnits(m_pGlyphFaceCache->m_pHead);
78 0 : if (!m_upem) return false;
79 : // m_glyphidx = new unsigned short[m_numGlyphs]; // only need this if doing occasional glyph reads
80 :
81 0 : return true;
82 : }
83 :
84 0 : bool Face::readGraphite()
85 : {
86 : size_t lSilf;
87 0 : const byte * const pSilf = getTable(Tag::Silf, &lSilf),
88 0 : * p = pSilf;
89 0 : if (!p) return false;
90 :
91 0 : const uint32 version = be::read<uint32>(p);
92 0 : if (version < 0x00020000) return false;
93 0 : if (version >= 0x00030000)
94 0 : be::skip<uint32>(p); // compilerVersion
95 0 : m_numSilf = be::read<uint16>(p);
96 0 : be::skip<uint16>(p); // reserved
97 :
98 0 : bool havePasses = false;
99 0 : m_silfs = new Silf[m_numSilf];
100 0 : for (int i = 0; i < m_numSilf; i++)
101 : {
102 0 : const uint32 offset = be::read<uint32>(p),
103 0 : next = i == m_numSilf - 1 ? lSilf : be::peek<uint32>(p);
104 0 : if (next > lSilf || offset >= next)
105 0 : return false;
106 :
107 0 : if (!m_silfs[i].readGraphite(pSilf + offset, next - offset, *this, version))
108 0 : return false;
109 :
110 0 : if (m_silfs[i].numPasses())
111 0 : havePasses = true;
112 : }
113 :
114 0 : return havePasses;
115 : }
116 :
117 0 : bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
118 : {
119 0 : return aSilf->runGraphite(seg, 0, aSilf->numPasses());
120 : }
121 :
122 0 : const Silf *Face::chooseSilf(uint32 script) const
123 : {
124 0 : if (m_numSilf == 0)
125 0 : return NULL;
126 0 : else if (m_numSilf == 1 || script == 0)
127 0 : return m_silfs;
128 : else // do more work here
129 0 : return m_silfs;
130 : }
131 :
132 0 : uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
133 : {
134 0 : switch (metrics(metric))
135 : {
136 0 : case kgmetAscent : return m_ascent;
137 0 : case kgmetDescent : return m_descent;
138 0 : default: return m_pGlyphFaceCache->glyph(gid)->getMetric(metric);
139 : }
140 : }
141 :
142 0 : void Face::takeFileFace(FileFace* pFileFace/*takes ownership*/)
143 : {
144 0 : if (m_pFileFace==pFileFace)
145 0 : return;
146 :
147 0 : delete m_pFileFace;
148 0 : m_pFileFace = pFileFace;
149 : }
150 :
151 0 : NameTable * Face::nameTable() const
152 : {
153 0 : if (m_pNames) return m_pNames;
154 0 : size_t tableLength = 0;
155 0 : const byte * table = getTable(Tag::name, &tableLength);
156 0 : if (table)
157 0 : m_pNames = new NameTable(table, tableLength);
158 0 : return m_pNames;
159 : }
160 :
161 0 : uint16 Face::languageForLocale(const char * locale) const
162 : {
163 0 : nameTable();
164 0 : if (m_pNames)
165 0 : return m_pNames->getLanguageId(locale);
166 0 : return 0;
167 : }
168 :
169 :
170 : #ifndef GRAPHITE2_NFILEFACE
171 :
172 : FileFace::FileFace(const char *filename) :
173 : m_pHeader(NULL),
174 : m_pTableDir(NULL)
175 : {
176 : if (!(m_pfile = fopen(filename, "rb"))) return;
177 : if (fseek(m_pfile, 0, SEEK_END)) return;
178 : m_lfile = ftell(m_pfile);
179 : if (fseek(m_pfile, 0, SEEK_SET)) return;
180 : size_t lOffset, lSize;
181 : if (!TtfUtil::GetHeaderInfo(lOffset, lSize)) return;
182 : m_pHeader = (TtfUtil::Sfnt::OffsetSubTable*)gralloc<char>(lSize);
183 : if (fseek(m_pfile, lOffset, SEEK_SET)) return;
184 : if (fread(m_pHeader, 1, lSize, m_pfile) != lSize) return;
185 : if (!TtfUtil::CheckHeader(m_pHeader)) return;
186 : if (!TtfUtil::GetTableDirInfo(m_pHeader, lOffset, lSize)) return;
187 : m_pTableDir = (TtfUtil::Sfnt::OffsetSubTable::Entry*)gralloc<char>(lSize);
188 : if (fseek(m_pfile, lOffset, SEEK_SET)) return;
189 : if (fread(m_pTableDir, 1, lSize, m_pfile) != lSize) return;
190 : }
191 :
192 : FileFace::~FileFace()
193 : {
194 : free(m_pTableDir);
195 : free(m_pHeader);
196 : if (m_pfile)
197 : fclose(m_pfile);
198 : m_pTableDir = NULL;
199 : m_pfile = NULL;
200 : m_pHeader = NULL;
201 : }
202 :
203 :
204 : const void *FileFace::table_fn(const void* appFaceHandle, unsigned int name, size_t *len)
205 : {
206 : const FileFace* ttfFaceHandle = (const FileFace*)appFaceHandle;
207 : TableCacheItem * tci = ttfFaceHandle->m_tables;
208 :
209 : switch (name)
210 : {
211 : case Tag::Feat: tci += 0; break;
212 : case Tag::Glat: tci += 1; break;
213 : case Tag::Gloc: tci += 2; break;
214 : case Tag::OS_2: tci += 3; break;
215 : case Tag::Sile: tci += 4; break;
216 : case Tag::Silf: tci += 5; break;
217 : case Tag::Sill: tci += 6; break;
218 : case Tag::cmap: tci += 7; break;
219 : case Tag::glyf: tci += 8; break;
220 : case Tag::hdmx: tci += 9; break;
221 : case Tag::head: tci += 10; break;
222 : case Tag::hhea: tci += 11; break;
223 : case Tag::hmtx: tci += 12; break;
224 : case Tag::kern: tci += 13; break;
225 : case Tag::loca: tci += 14; break;
226 : case Tag::maxp: tci += 15; break;
227 : case Tag::name: tci += 16; break;
228 : case Tag::post: tci += 17; break;
229 : default: tci = 0; break;
230 : }
231 :
232 : assert(tci); // don't expect any other table types
233 : if (!tci) return NULL;
234 : if (tci->data() == NULL)
235 : {
236 : char *tptr;
237 : size_t tlen, lOffset;
238 : if (!TtfUtil::GetTableInfo(name, ttfFaceHandle->m_pHeader, ttfFaceHandle->m_pTableDir, lOffset, tlen)) return NULL;
239 : if (fseek(ttfFaceHandle->m_pfile, lOffset, SEEK_SET)) return NULL;
240 : if (lOffset + tlen > ttfFaceHandle->m_lfile) return NULL;
241 : tptr = gralloc<char>(tlen);
242 : if (fread(tptr, 1, tlen, ttfFaceHandle->m_pfile) != tlen)
243 : {
244 : free(tptr);
245 : return NULL;
246 : }
247 : tci->set(tptr, tlen);
248 : }
249 : if (len) *len = tci->size();
250 : return tci->data();
251 : }
252 : #endif //!GRAPHITE2_NFILEFACE
|