⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gameswf_font.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
字号:
// gameswf_font.cpp	-- Thatcher Ulrich <tu@tulrich.com> 2003// This source code has been donated to the Public Domain.  Do// whatever you want with it.// A font type for gameswf.#include "gameswf_font.h"#include "gameswf_stream.h"#include "gameswf_impl.h"#include "gameswf_log.h"#include "gameswf_shape.h"#include "base/tu_file.h"namespace gameswf{	font::font()		:		m_texture_glyph_nominal_size(96),	// Default is not important; gets overridden during glyph generation		m_name(NULL),		m_owning_movie(NULL),		m_unicode_chars(false),		m_shift_jis_chars(false),		m_ansi_chars(true),		m_is_italic(false),		m_is_bold(false),		m_wide_codes(false),		m_ascent(0.0f),		m_descent(0.0f),		m_leading(0.0f)	{	}	font::~font()	{		m_glyphs.resize(0);		// Delete the name string.		if (m_name)		{			delete [] m_name;			m_name = NULL;		}	}	shape_character_def*	font::get_glyph(int index) const	{		if (index >= 0 && index < m_glyphs.size())		{			return m_glyphs[index].get_ptr();		}		else		{			return NULL;		}	}	const texture_glyph&	font::get_texture_glyph(int glyph_index) const	// Return a pointer to a texture_glyph struct corresponding to	// the given glyph_index, if we have one.  Otherwise return NULL.	{		if (glyph_index < 0 || glyph_index >= m_texture_glyphs.size())		{			static const texture_glyph	s_dummy_texture_glyph;			return s_dummy_texture_glyph;		}		return m_texture_glyphs[glyph_index];	}	void	font::add_texture_glyph(int glyph_index, const texture_glyph& glyph)	// Register some texture info for the glyph at the specified	// index.  The texture_glyph can be used later to render the	// glyph.	{		assert(glyph_index >= 0 && glyph_index < m_glyphs.size());		assert(m_texture_glyphs.size() == m_glyphs.size());		assert(glyph.is_renderable());		assert(m_texture_glyphs[glyph_index].is_renderable() == false);		m_texture_glyphs[glyph_index] = glyph;	}	void	font::wipe_texture_glyphs()	// Delete all our texture glyph info.	{		assert(m_texture_glyphs.size() == m_glyphs.size());		// Replace with default (empty) glyph info.		texture_glyph	default_tg;		for (int i = 0, n = m_texture_glyphs.size(); i < n; i++)		{			m_texture_glyphs[i] = default_tg;		}	}	void	font::read(stream* in, int tag_type, movie_definition_sub* m)	{		assert(tag_type == 10 || tag_type == 48);		// No add_ref() here, to avoid cycle.  m_owning_movie is our owner, so it has a ref to us.		m_owning_movie = m;		if (tag_type == 10)		{			IF_VERBOSE_PARSE(log_msg("reading DefineFont\n"));			int	table_base = in->get_position();			// Read the glyph offsets.  Offsets			// are measured from the start of the			// offset table.			array<int>	offsets;			offsets.push_back(in->read_u16());			IF_VERBOSE_PARSE(log_msg("offset[0] = %d\n", offsets[0]));			int	count = offsets[0] >> 1;			for (int i = 1; i < count; i++)			{				offsets.push_back(in->read_u16());				IF_VERBOSE_PARSE(log_msg("offset[%d] = %d\n", i, offsets[i]));			}			m_glyphs.resize(count);			m_texture_glyphs.resize(m_glyphs.size());			if (m->get_create_font_shapes() == DO_LOAD_FONT_SHAPES)			{				// Read the glyph shapes.				{for (int i = 0; i < count; i++)				{					// Seek to the start of the shape data.					int	new_pos = table_base + offsets[i];					in->set_position(new_pos);					// Create & read the shape.					shape_character_def* s = new shape_character_def;					s->read(in, 2, false, m);					m_glyphs[i] = s;				}}			}		}		else if (tag_type == 48)		{			IF_VERBOSE_PARSE(log_msg("reading DefineFont2\n"));			bool	has_layout = (in->read_uint(1) != 0);			m_shift_jis_chars = (in->read_uint(1) != 0);			m_unicode_chars = (in->read_uint(1) != 0);			m_ansi_chars = (in->read_uint(1) != 0);			bool	wide_offsets = (in->read_uint(1) != 0);			m_wide_codes = (in->read_uint(1) != 0);			m_is_italic = (in->read_uint(1) != 0);			m_is_bold = (in->read_uint(1) != 0);			Uint8	reserved = in->read_u8();			// Inhibit warning.			reserved = reserved;			m_name = in->read_string_with_length();			int	glyph_count = in->read_u16();						int	table_base = in->get_position();			// Read the glyph offsets.  Offsets			// are measured from the start of the			// offset table.			array<int>	offsets;			int	font_code_offset;			if (wide_offsets)			{				// 32-bit offsets.				for (int i = 0; i < glyph_count; i++)				{					offsets.push_back(in->read_u32());				}				font_code_offset = in->read_u32();			}			else			{				// 16-bit offsets.				for (int i = 0; i < glyph_count; i++)				{					offsets.push_back(in->read_u16());				}				font_code_offset = in->read_u16();			}			m_glyphs.resize(glyph_count);			m_texture_glyphs.resize(m_glyphs.size());			if (m->get_create_font_shapes() == DO_LOAD_FONT_SHAPES)			{				// Read the glyph shapes.				{for (int i = 0; i < glyph_count; i++)				{					// Seek to the start of the shape data.					int	new_pos = table_base + offsets[i];					// if we're seeking backwards, then that looks like a bug.					assert(new_pos >= in->get_position());					in->set_position(new_pos);					// Create & read the shape.					shape_character_def* s = new shape_character_def;					s->read(in, 22, false, m);					m_glyphs[i] = s;				}}				int	current_position = in->get_position();				if (font_code_offset + table_base != current_position)				{					// Bad offset!  Don't try to read any more.					return;				}			}			else			{				// Skip the shape data.				int	new_pos = table_base + font_code_offset;				if (new_pos >= in->get_tag_end_position())				{					// No layout data!					return;				}				in->set_position(new_pos);			}			read_code_table(in);			// Read layout info for the glyphs.			if (has_layout)			{				m_ascent = (float) in->read_s16();				m_descent = (float) in->read_s16();				m_leading = (float) in->read_s16();								// Advance table; i.e. how wide each character is.				m_advance_table.resize(m_glyphs.size());				for (int i = 0, n = m_advance_table.size(); i < n; i++)				{					m_advance_table[i] = (float) in->read_s16();				}				// Bounds table.				//m_bounds_table.resize(m_glyphs.size());	// kill				rect	dummy_rect;				{for (int i = 0, n = m_glyphs.size(); i < n; i++)				{					//m_bounds_table[i].read(in);	// kill					dummy_rect.read(in);				}}				// Kerning pairs.				int	kerning_count = in->read_u16();				{for (int i = 0; i < kerning_count; i++)				{					Uint16	char0, char1;					if (m_wide_codes)					{						char0 = in->read_u16();						char1 = in->read_u16();					}					else					{						char0 = in->read_u8();						char1 = in->read_u8();					}					float	adjustment = (float) in->read_s16();					kerning_pair	k;					k.m_char0 = char0;					k.m_char1 = char1;					// Remember this adjustment; we can look it up quickly					// later using the character pair as the key.					m_kerning_pairs.add(k, adjustment);				}}			}		}	}	void	font::read_font_info(stream* in)	// Read additional information about this font, from a	// DefineFontInfo tag.  The caller has already read the tag	// type and font id.	{		if (m_name)		{			delete m_name;			m_name = NULL;		}		m_name = in->read_string_with_length();		unsigned char	flags = in->read_u8();		m_unicode_chars = (flags & 0x20) != 0;		m_shift_jis_chars = (flags & 0x10) != 0;		m_ansi_chars = (flags & 0x08) != 0;		m_is_italic = (flags & 0x04) != 0;		m_is_bold = (flags & 0x02) != 0;		m_wide_codes = (flags & 0x01) != 0;		read_code_table(in);	}	void	font::read_code_table(stream* in)	// Read the table that maps from glyph indices to character	// codes.	{		IF_VERBOSE_PARSE(log_msg("reading code table at offset %d\n", in->get_position()));		assert(m_code_table.is_empty());		if (m_wide_codes)		{			// Code table is made of Uint16's.			for (int i = 0; i < m_glyphs.size(); i++)			{				m_code_table.add(in->read_u16(), i);			}		}		else		{			// Code table is made of bytes.			for (int i = 0; i < m_glyphs.size(); i++)			{				m_code_table.add(in->read_u8(), i);			}		}	}	int	font::get_glyph_index(Uint16 code) const	{		int glyph_index;		if (m_code_table.get(code, &glyph_index))		{			return glyph_index;		}		return -1;	}	float	font::get_advance(int glyph_index) const	{		if (glyph_index == -1)		{			// Default advance.			return 512.0f;		}		if (m_advance_table.size() == 0)		{			// No layout info for this font!!!			static bool	s_logged = false;			if (s_logged == false)			{				s_logged = true;				log_error("error: empty advance table in font %s\n", get_name());			}			return 0;		}		if (glyph_index < m_advance_table.size())		{			assert(glyph_index >= 0);			return m_advance_table[glyph_index];		}		else		{			// Bad glyph index.  Due to bad data file?			assert(0);			return 0;		}	}	float	font::get_kerning_adjustment(int last_code, int code) const	// Return the adjustment in advance between the given two	// characters.  Normally this will be 0; i.e. the 	{		float	adjustment;		kerning_pair	k;		k.m_char0 = last_code;		k.m_char1 = code;		if (m_kerning_pairs.get(k, &adjustment))		{			return adjustment;		}		return 0;	}	void	font::output_cached_data(tu_file* out, const cache_options& options)	// Dump our cached data into the given stream.	{// @@ Disabled.  Need to fix input_cached_data, so that it has a// reliable and cheap way to skip over data for NULL glyphs.#if 0		// Dump cached shape data for glyphs (i.e. this will		// be tesselations used to render larger glyph sizes).		int	 n = m_glyphs.size();		out->write_le32(n);		for (int i = 0; i < n; i++)		{			shape_character_def*	s = m_glyphs[i].get_ptr();			if (s)			{				s->output_cached_data(out, options);			}		}#endif // 0	}		void	font::input_cached_data(tu_file* in)	// Read our cached data from the given stream.	{// @@ Disable.  See comment in output_cached_data().#if 0		// Read cached shape data for glyphs.		int	n = in->read_le32();		if (n != m_glyphs.size())		{			log_error("error reading cache file in font::input_cached_data() "				  "glyph count mismatch.\n");			in->go_to_end();	// ensure that no more data will be read from this stream.			return;		}		for (int i = 0; i < n; i++)		{			m_glyphs[i]->input_cached_data(in);		}#endif // 0	}};	// end namespace gameswf// Local Variables:// mode: C++// c-basic-offset: 8 // tab-width: 8// indent-tabs-mode: t// End:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -