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

📄 gameswf_text.cpp

📁 一个开源的Flash 播放器,可以在Windows/Linux 上运行
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		// Reset our text bounding box to the given point.		{			m_text_bounding_box.m_x_min = x;			m_text_bounding_box.m_x_max = x;			m_text_bounding_box.m_y_min = y;			m_text_bounding_box.m_y_max = y;		}		virtual void	set_text_value(const char* new_text)		// Set our text to the given string.		{			if (m_text == new_text)			{				return;			}			m_text = new_text;			if (m_def->m_max_length > 0			    && m_text.length() > m_def->m_max_length)			{				m_text.resize(m_def->m_max_length);			}			format_text();		}		virtual const char*	get_text_value() const		{			return m_text.c_str();		}		void	set_member(const tu_stringi& name, const as_value& val)		// We have a "text" member.		{			// @@ TODO need to inherit basic stuff like _x, _y, _xscale, _yscale etc			as_standard_member	std_member = get_standard_member(name);			switch (std_member)			{			default:			case M_INVALID_MEMBER:				break;			case M_TEXT:				//if (name == "text")			{				int version = get_parent()->get_movie_definition()->get_version();				set_text_value(val.to_tu_string_versioned(version));				return;			}			case M_X:				//else if (name == "_x")			{				matrix	m = get_matrix();				m.m_[0][2] = (float) PIXELS_TO_TWIPS(val.to_number());				set_matrix(m);				// m_accept_anim_moves = false;								return;			}			case M_Y:				//else if (name == "_y")			{				matrix	m = get_matrix();				m.m_[1][2] = (float) PIXELS_TO_TWIPS(val.to_number());				set_matrix(m);				// m_accept_anim_moves = false;								return;			}			case M_VISIBLE:				//else if (name == "_visible")			{				set_visible(val.to_bool());				return;			}			case M_ALPHA:				//else if (name == "_alpha")			{				// @@ TODO this should be generic to struct character!				// Arg is in percent.				cxform	cx = get_cxform();				cx.m_[3][0] = fclamp(float(val.to_number()) / 100.f, 0, 1);				set_cxform(cx);				return;			}			case M_TEXTCOLOR:				//else if (name == "textColor")			{					// The arg is 0xRRGGBB format.				Uint32	rgb = (Uint32) val.to_number();				cxform	cx = get_cxform();				cx.m_[0][0] = fclamp(((rgb >> 16) & 255) / 255.0f, 0, 1);				cx.m_[1][0] = fclamp(((rgb >>  8) & 255) / 255.0f, 0, 1);				cx.m_[2][0] = fclamp(((rgb      ) & 255) / 255.0f, 0, 1);				set_cxform(cx);				return;			}			// @@ TODO see TextField members in Flash MX docs			}	// end switch		}		bool	get_member(const tu_stringi& name, as_value* val)		{			as_standard_member	std_member = get_standard_member(name);			switch (std_member)			{			default:			case M_INVALID_MEMBER:				break;			case M_TEXT:				//if (name == "text")			{				val->set_tu_string(m_text);				return true;			}			case M_VISIBLE:				//else if (name == "_visible")			{				val->set_bool(get_visible());				return true;			}			case M_ALPHA:				//else if (name == "_alpha")			{				// @@ TODO this should be generic to struct character!				const cxform&	cx = get_cxform();				val->set_double(cx.m_[3][0] * 100.f);				return true;			}			case M_TEXTCOLOR:				//else if (name == "textColor")			{				// Return color in 0xRRGGBB format				const cxform&	cx = get_cxform();				int	r = iclamp(int(cx.m_[0][0] * 255), 0, 255);				int	g = iclamp(int(cx.m_[0][0] * 255), 0, 255);				int	b = iclamp(int(cx.m_[0][0] * 255), 0, 255);				val->set_int((r << 16) + (g << 8) + b);				return true;			}			case M_X:				//else if (name == "_x")			{				matrix	m = get_matrix();	// @@ get_world_matrix()???				val->set_double(TWIPS_TO_PIXELS(m.m_[0][2]));				return true;			}			case M_Y:				//else if (name == "_y")			{				matrix	m = get_matrix();	// @@ get_world_matrix()???				val->set_double(TWIPS_TO_PIXELS(m.m_[1][2]));				return true;			}			case M_WIDTH:				//else if (name == "_width")			{				// @@ TODO should implement this in				// character and inherit into both here and sprite_instance				rect	transformed_rect;				transformed_rect.enclose_transformed_rect(get_world_matrix(), m_def->m_rect);				val->set_double(TWIPS_TO_PIXELS(transformed_rect.width()));				return true;			}			case M_HEIGHT:				//else if (name == "_height")			{				// @@ TODO should implement this in				// character and inherit into both here and sprite_instance				rect	transformed_rect;				transformed_rect.enclose_transformed_rect(get_world_matrix(), m_def->m_rect);				val->set_double(TWIPS_TO_PIXELS(transformed_rect.height()));				return true;			}			case M_TEXTWIDTH:				//else if (name == "textWidth")			{				// Return the width, in pixels, of the text as laid out.				// (I.e. the actual text content, not our defined				// bounding box.)				//				// In local coords.  Verified against Macromedia Flash.				val->set_double(TWIPS_TO_PIXELS(m_text_bounding_box.width()));				return true;			}			}	// end switch			return false;		}				// @@ WIDTH_FUDGE is a total fudge to make it match the Flash player!  Maybe		// we have a bug?		#define WIDTH_FUDGE 80.0f		void	align_line(edit_text_character_def::alignment align, int last_line_start_record, float x)		// Does LEFT/CENTER/RIGHT alignment on the records in		// m_text_glyph_records[], starting with		// last_line_start_record and going through the end of		// m_text_glyph_records.		{			float	extra_space = (m_def->m_rect.width() - m_def->m_right_margin) - x - WIDTH_FUDGE;			assert(extra_space >= 0.0f);			float	shift_right = 0.0f;			if (align == edit_text_character_def::ALIGN_LEFT)			{				// Nothing to do; already aligned left.				return;			}			else if (align == edit_text_character_def::ALIGN_CENTER)			{				// Distribute the space evenly on both sides.				shift_right = extra_space / 2;			}			else if (align == edit_text_character_def::ALIGN_RIGHT)			{				// Shift all the way to the right.				shift_right = extra_space;			}			// Shift the beginnings of the records on this line.			for (int i = last_line_start_record; i < m_text_glyph_records.size(); i++)			{				text_glyph_record&	rec = m_text_glyph_records[i];				if (rec.m_style.m_has_x_offset)				{					rec.m_style.m_x_offset += shift_right;				}			}		}		// Convert the characters in m_text into a series of		// text_glyph_records to be rendered.		void	format_text()		{			m_text_glyph_records.resize(0);			if (m_def->m_font == NULL)			{				return;			}			// @@ mostly for debugging			// Font substitution -- if the font has no			// glyphs, try some other defined font!			if (m_def->m_font->get_glyph_count() == 0)			{				// Find a better font.				font*	newfont = m_def->m_font;				for (int i = 0, n = fontlib::get_font_count(); i < n; i++)				{					font*	f = fontlib::get_font(i);					assert(f);					if (f->get_glyph_count() > 0)					{						// This one looks good.						newfont = f;						break;					}				}				if (m_def->m_font != newfont)				{					log_error("error: substituting font!  font '%s' has no glyphs, using font '%s'\n",						  fontlib::get_font_name(m_def->m_font),						  fontlib::get_font_name(newfont));					m_def->m_font = newfont;				}			}			float	scale = m_def->m_text_height / 1024.0f;	// the EM square is 1024 x 1024			text_glyph_record	rec;	// one to work on			rec.m_style.m_font = m_def->m_font;			rec.m_style.m_color = m_def->m_color;			rec.m_style.m_x_offset = fmax(0, m_def->m_left_margin + m_def->m_indent);			rec.m_style.m_y_offset = m_def->m_text_height				+ (m_def->m_font->get_leading() - m_def->m_font->get_descent()) * scale;			rec.m_style.m_text_height = m_def->m_text_height;			rec.m_style.m_has_x_offset = true;			rec.m_style.m_has_y_offset = true;			float	x = rec.m_style.m_x_offset;			float	y = rec.m_style.m_y_offset;			// Start the bbox at the upper-left corner of the first glyph. 			reset_bounding_box(x, y - m_def->m_font->get_descent() * scale + m_def->m_text_height);			float	leading = m_def->m_leading;			leading += m_def->m_font->get_leading() * scale;			int	last_code = -1;			int	last_space_glyph = -1;			int	last_line_start_record = 0;			const char*	text = &m_text[0];			while (Uint32 code = utf8::decode_next_unicode_character(&text))			{// @@ try to truncate overflow text??#if 0				if (y + m_def->m_font->get_descent() * scale > m_def->m_rect.height())				{					// Text goes below the bottom of our bounding box.					rec.m_glyphs.resize(0);					break;				}#endif // 0				//Uint16	code = m_text[j];				x += m_def->m_font->get_kerning_adjustment(last_code, (int) code) * scale;				last_code = (int) code;				// Expand the bounding-box to the lower-right corner of each glyph as				// we generate it.				m_text_bounding_box.expand_to_point(x, y + m_def->m_font->get_descent() * scale);				if (code == 13 || code == 10)				{					// newline.					// Frigging Flash seems to use '\r' (13) as its					// default newline character.  If we get DOS-style \r\n					// sequences, it'll show up as double newlines, so maybe we					// need to detect \r\n and treat it as one newline.					// Close out this stretch of glyphs.					m_text_glyph_records.push_back(rec);					align_line(m_def->m_alignment, last_line_start_record, x);					x = fmax(0, m_def->m_left_margin + m_def->m_indent);	// new paragraphs get the indent.					y += m_def->m_text_height + leading;					// Start a new record on the next line.					rec.m_glyphs.resize(0);					rec.m_style.m_font = m_def->m_font;					rec.m_style.m_color = m_def->m_color;					rec.m_style.m_x_offset = x;					rec.m_style.m_y_offset = y;					rec.m_style.m_text_height = m_def->m_text_height;					rec.m_style.m_has_x_offset = true;					rec.m_style.m_has_y_offset = true;					last_space_glyph = -1;					last_line_start_record = m_text_glyph_records.size();					continue;				}				if (code == 8)				{					// backspace (ASCII BS).					// This is a limited hack to enable overstrike effects.					// It backs the cursor up by one character and then continues					// the layout.  E.g. you can use this to display an underline					// cursor inside a simulated text-entry box.					//					// ActionScript understands the '\b' escape sequence					// for inserting a BS character.					//					// ONLY WORKS FOR BACKSPACING OVER ONE CHARACTER, WON'T BS					// OVER NEWLINES, ETC.					if (rec.m_glyphs.size() > 0)					{						// Peek at the previous glyph, and zero out its advance						// value, so the next char overwrites it.						float	advance = rec.m_glyphs.back().m_glyph_advance;						x -= advance;	// maintain formatting						rec.m_glyphs.back().m_glyph_advance = 0;	// do the BS effect					}					continue;				}				// Remember where word breaks occur.				if (code == 32)				{					last_space_glyph = rec.m_glyphs.size();				}				int	index = m_def->m_font->get_glyph_index((Uint16) code);				if (index == -1)				{					// error -- missing glyph!										// Log an error, but don't log too many times.					static int	s_log_count = 0;					if (s_log_count < 10)					{						s_log_count++;						log_error("edit_text_character::display() -- missing glyph for char %d "							  "-- make sure character shapes for font %s are being exported "							  "into your SWF file!\n",							  code,							  m_def->m_font->get_name());					}					// Drop through and use index == -1; this will display					// using the empty-box glyph				}				text_glyph_record::glyph_entry	ge;				ge.m_glyph_index = index;				ge.m_glyph_advance = scale * m_def->m_font->get_advance(index);				rec.m_glyphs.push_back(ge);				x += ge.m_glyph_advance;								if (x >= m_def->m_rect.width() - m_def->m_right_margin - WIDTH_FUDGE)				{					// Whoops, we just exceeded the box width.  Do word-wrap.					// Insert newline.					// Close out this stretch of glyphs.					m_text_glyph_records.push_back(rec);					float	previous_x = x;					x = m_def->m_left_margin;					y += m_def->m_text_height + leading;					// Start a new record on the next line.					rec.m_glyphs.resize(0);					rec.m_style.m_font = m_def->m_font;					rec.m_style.m_color = m_def->m_color;					rec.m_style.m_x_offset = x;					rec.m_style.m_y_offset = y;					rec.m_style.m_text_height = m_def->m_text_height;					rec.m_style.m_has_x_offset = true;					rec.m_style.m_has_y_offset = true;										text_glyph_record&	last_line = m_text_glyph_records.back();					if (last_space_glyph == -1)					{						// Pull the previous glyph down onto the						// new line.						if (last_line.m_glyphs.size() > 0)						{							rec.m_glyphs.push_back(last_line.m_glyphs.back());							x += last_line.m_glyphs.back().m_glyph_advance;							previous_x -= last_line.m_glyphs.back().m_glyph_advance;							last_line.m_glyphs.resize(last_line.m_glyphs.size() - 1);						}					}					else					{						// Move the previous word down onto the next line.						previous_x -= last_line.m_glyphs[last_space_glyph].m_glyph_advance;						for (int i = last_space_glyph + 1; i < last_line.m_glyphs.size(); i++)						{							rec.m_glyphs.push_back(last_line.m_glyphs[i]);							x += last_line.m_glyphs[i].m_glyph_advance;							previous_x -= last_line.m_glyphs[i].m_glyph_advance;						}						last_line.m_glyphs.resize(last_space_glyph);					}					align_line(m_def->m_alignment, last_line_start_record, previous_x);					last_space_glyph = -1;					last_line_start_record = m_text_glyph_records.size();				}				// TODO: HTML markup			}			// Add this line to our output.			m_text_glyph_records.push_back(rec);			align_line(m_def->m_alignment, last_line_start_record, x);		}		void	display()		// Draw the dynamic string.		{			if (m_def->m_border)			{				matrix	mat = get_world_matrix();								// @@ hm, should we apply the color xform?  It seems logical; need to test.				// cxform	cx = get_world_cxform();				// Show white background + black bounding box.				render::set_matrix(mat);				point	coords[4];				coords[0] = m_def->m_rect.get_corner(0);				coords[1] = m_def->m_rect.get_corner(1);				coords[2] = m_def->m_rect.get_corner(3);				coords[3] = m_def->m_rect.get_corner(2);				Sint16	icoords[18] = 				{					// strip (fill in)					(Sint16) coords[0].m_x, (Sint16) coords[0].m_y,					(Sint16) coords[1].m_x, (Sint16) coords[1].m_y,					(Sint16) coords[2].m_x, (Sint16) coords[2].m_y,					(Sint16) coords[3].m_x, (Sint16) coords[3].m_y,					// outline					(Sint16) coords[0].m_x, (Sint16) coords[0].m_y,					(Sint16) coords[1].m_x, (Sint16) coords[1].m_y,					(Sint16) coords[3].m_x, (Sint16) coords[3].m_y,					(Sint16) coords[2].m_x, (Sint16) coords[2].m_y,					(Sint16) coords[0].m_x, (Sint16) coords[0].m_y,				};								render::fill_style_color(0, rgba(255, 255, 255, 255));				render::draw_mesh_strip(&icoords[0], 4);				render::line_style_color(rgba(0,0,0,255));				render::draw_line_strip(&icoords[8], 5);			}			// Draw our actual text.			display_glyph_records(matrix::identity, this, m_text_glyph_records, m_def->m_root_def);			do_display_callback();		}	};	character*	edit_text_character_def::create_character_instance(movie* parent, int id)	{		if (m_font == NULL)		{			// Resolve the font, if possible.			m_font = m_root_def->get_font(m_font_id);			if (m_font == NULL)			{				log_error("error: text style with undefined font; font_id = %d\n", m_font_id);			}		}		edit_text_character*	ch = new edit_text_character(parent, this, id);		ch->set_name(m_default_name.c_str());		return ch;	}	void	define_edit_text_loader(stream* in, int tag_type, movie_definition_sub* m)	// Read a DefineText tag.	{		assert(tag_type == 37);		Uint16	character_id = in->read_u16();		edit_text_character_def*	ch = new edit_text_character_def(m);		IF_VERBOSE_PARSE(log_msg("edit_text_char, id = %d\n", character_id));		ch->read(in, tag_type, m);		m->add_character(character_id, ch);	}}	// 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 + -