use the VERSION instead of master in the revno.h generated from a src tarball
[gnash.git] / libcore / Font.cpp
blobfd55ac865afcc4cfb3b03f6d9b5c5ecb435d4557
1 // Font.cpp: ActionScript Font handling, for Gnash.
2 //
3 // Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the 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
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 // Based on the public domain work of Thatcher Ulrich <tu@tulrich.com> 2003
24 #include "smart_ptr.h"
25 #include "Font.h"
26 #include "log.h"
27 #include "ShapeRecord.h"
28 #include "DefineFontTag.h"
29 #include "FreetypeGlyphsProvider.h"
31 #include <utility> // for std::make_pair
32 #include <memory>
34 namespace gnash {
36 namespace {
38 /// Reverse lookup of Glyph in CodeTable.
40 /// Inefficient, which is probably why TextSnapshot was designed like it
41 /// is.
42 class CodeLookup
44 public:
45 CodeLookup(const int glyph) : _glyph(glyph) {}
47 bool operator()(const std::pair<const boost::uint16_t, int>& p) {
48 return p.second == _glyph;
51 private:
52 int _glyph;
57 Font::GlyphInfo::GlyphInfo()
59 advance(0)
62 Font::GlyphInfo::GlyphInfo(std::auto_ptr<SWF::ShapeRecord> glyph,
63 float advance)
65 glyph(glyph.release()),
66 advance(advance)
69 Font::GlyphInfo::GlyphInfo(const GlyphInfo& o)
71 glyph(o.glyph),
72 advance(o.advance)
76 Font::Font(std::auto_ptr<SWF::DefineFontTag> ft)
78 _fontTag(ft.release()),
79 _name(_fontTag->name()),
80 _unicodeChars(_fontTag->unicodeChars()),
81 _shiftJISChars(_fontTag->shiftJISChars()),
82 _ansiChars(_fontTag->ansiChars()),
83 _italic(_fontTag->italic()),
84 _bold(_fontTag->bold())
86 if (_fontTag->hasCodeTable()) _embeddedCodeTable = _fontTag->getCodeTable();
89 Font::Font(const std::string& name, bool bold, bool italic)
91 _fontTag(0),
92 _name(name),
93 _unicodeChars(false),
94 _shiftJISChars(false),
95 _ansiChars(true),
96 _italic(italic),
97 _bold(bold)
99 assert(!_name.empty());
102 Font::~Font()
106 SWF::ShapeRecord*
107 Font::get_glyph(int index, bool embedded) const
109 // What to do if embedded is true and this is a
110 // device-only font?
111 const GlyphInfoRecords& lookup = (embedded && _fontTag) ?
112 _fontTag->glyphTable() : _deviceGlyphTable;
114 if (index >= 0 && (size_t)index < lookup.size()) {
115 return lookup[index].glyph.get();
118 // TODO: should we log an error here ?
119 return 0;
122 void
123 Font::addFontNameInfo(const FontNameInfo& fontName)
125 if (!_displayName.empty() || !_copyrightName.empty())
127 IF_VERBOSE_MALFORMED_SWF(
128 log_swferror(_("Attempt to set font display or copyright name "
129 "again. This should mean there is more than one "
130 "DefineFontName tag referring to the same Font. Don't "
131 "know what to do in this case, so ignoring."));
133 return;
136 _displayName = fontName.displayName;
137 _copyrightName = fontName.copyrightName;
141 Font::GlyphInfoRecords::size_type
142 Font::glyphCount() const
144 assert(_fontTag);
145 return _fontTag->glyphTable().size();
149 void
150 Font::setFlags(boost::uint8_t flags)
152 _shiftJISChars = flags & (1 << 6);
153 _unicodeChars = flags & (1 << 5);
154 _ansiChars = flags & (1 << 4);
155 _italic = flags & (1 << 1);
156 _bold = flags & (1 << 0);
160 void
161 Font::setCodeTable(std::auto_ptr<CodeTable> table)
163 if (_embeddedCodeTable)
165 IF_VERBOSE_MALFORMED_SWF(
166 log_swferror(_("Attempt to add an embedded glyph CodeTable to "
167 "a font that already has one. This should mean there "
168 "are several DefineFontInfo tags, or a DefineFontInfo "
169 "tag refers to a font created by DefineFone2 or "
170 "DefineFont3. Don't know what should happen in this "
171 "case, so ignoring."));
173 return;
175 _embeddedCodeTable.reset(table.release());
179 void
180 Font::setName(const std::string& name)
182 _name = name;
186 boost::uint16_t
187 Font::codeTableLookup(int glyph, bool embedded) const
189 const CodeTable& ctable = (embedded && _embeddedCodeTable) ?
190 *_embeddedCodeTable : _deviceCodeTable;
192 CodeTable::const_iterator it = std::find_if(ctable.begin(), ctable.end(),
193 CodeLookup(glyph));
194 assert (it != ctable.end());
195 return it->first;
199 Font::get_glyph_index(boost::uint16_t code, bool embedded) const
201 const CodeTable& ctable = (embedded && _embeddedCodeTable) ?
202 *_embeddedCodeTable : _deviceCodeTable;
204 int glyph_index = -1;
205 CodeTable::const_iterator it = ctable.find(code);
206 if (it != ctable.end()) {
207 glyph_index = it->second;
208 return glyph_index;
211 // Try adding an os font, if possible
212 if (!embedded) {
213 glyph_index = const_cast<Font*>(this)->add_os_glyph(code);
215 return glyph_index;
218 float
219 Font::get_advance(int glyph_index, bool embedded) const
221 // What to do if embedded is true and this is a
222 // device-only font?
223 const GlyphInfoRecords& lookup = (embedded && _fontTag) ?
224 _fontTag->glyphTable() : _deviceGlyphTable;
226 if (glyph_index < 0) {
227 // Default advance.
228 return 512.0f;
231 assert(static_cast<size_t>(glyph_index) < lookup.size());
232 assert(glyph_index >= 0);
234 return lookup[glyph_index].advance;
238 // Return the adjustment in advance between the given two
239 // DisplayObjects. Normally this will be 0; i.e. the
240 float
241 Font::get_kerning_adjustment(int last_code, int code) const
243 kerning_pair k;
244 k.m_char0 = last_code;
245 k.m_char1 = code;
246 kernings_table::const_iterator it = m_kerning_pairs.find(k);
247 if (it != m_kerning_pairs.end()) {
248 float adjustment = it->second;
249 return adjustment;
251 return 0;
254 size_t
255 Font::unitsPerEM(bool embed) const
257 // the EM square is 1024 x 1024 for DefineFont up to 2
258 // and 20 as much for DefineFont3 up
259 if (embed) {
260 if ( _fontTag && _fontTag->subpixelFont() ) return 1024 * 20.0;
261 else return 1024;
264 FreetypeGlyphsProvider* ft = ftProvider();
265 if (!ft) {
266 log_error("Device font provider was not initialized, "
267 "can't get unitsPerEM");
268 return 0;
271 return ft->unitsPerEM();
275 Font::add_os_glyph(boost::uint16_t code)
277 FreetypeGlyphsProvider* ft = ftProvider();
278 if (!ft) return -1;
280 assert(_deviceCodeTable.find(code) == _deviceCodeTable.end());
282 float advance;
284 // Get the vectorial glyph
285 std::auto_ptr<SWF::ShapeRecord> sh = ft->getGlyph(code, advance);
287 if (!sh.get()) {
288 log_error("Could not create shape "
289 "glyph for DisplayObject code %u (%c) with "
290 "device font %s (%p)", code, code, _name, ft);
291 return -1;
294 // Find new glyph offset
295 int newOffset = _deviceGlyphTable.size();
297 // Add the new glyph id
298 _deviceCodeTable[code] = newOffset;
300 _deviceGlyphTable.push_back(GlyphInfo(sh, advance));
302 return newOffset;
305 bool
306 Font::matches(const std::string& name, bool bold, bool italic) const
308 return (_bold == bold && _italic == italic && name ==_name);
311 float
312 Font::leading() const {
313 return _fontTag ? _fontTag->leading() : 0.0f;
316 FreetypeGlyphsProvider*
317 Font::ftProvider() const
319 if (_ftProvider.get()) return _ftProvider.get();
321 if (_name.empty()) {
322 log_error("No name associated with this font, can't use device "
323 "fonts (should I use a default one?)");
324 return 0;
327 _ftProvider = FreetypeGlyphsProvider::createFace(_name, _bold, _italic);
329 if (!_ftProvider.get()) {
330 log_error("Could not create a freetype face %s", _name);
331 return 0;
334 return _ftProvider.get();
337 float
338 Font::ascent(bool embedded) const
340 if (embedded && _fontTag) return _fontTag->ascent();
341 FreetypeGlyphsProvider* ft = ftProvider();
342 if (ft) return ft->ascent();
343 return 0;
346 float
347 Font::descent(bool embedded) const
349 if (embedded && _fontTag) return _fontTag->descent();
350 FreetypeGlyphsProvider* ft = ftProvider();
351 if (ft) return ft->descent();
352 return 0;
355 } // namespace gnash
357 // Local Variables:
358 // mode: C++
359 // indent-tabs-mode: t
360 // End: