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

📄 gameswf_shape.cpp

📁 一个开源的嵌入式flash播放器 具体看文档和例子就可
💻 CPP
📖 第 1 页 / 共 3 页
字号:
						current_path.m_ay = y;					}					int	style = in->read_uint(num_line_bits);					if (style > 0)					{						style += line_base;					}					current_path.m_line = style;					if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg("  shape_character_read: line = %d\n", current_path.m_line));				}				if (flags & 0x10) {					assert(tag_type >= 22);					IF_VERBOSE_PARSE(log_msg("  shape_character read: more fill styles\n"));					// Store the current path if any.					if (! current_path.is_empty())					{						m_paths.push_back(current_path);						current_path.m_edges.resize(0);						// Clear styles.						current_path.m_fill0 = -1;						current_path.m_fill1 = -1;						current_path.m_line = -1;					}					// Tack on an empty path signalling a new shape.					// @@ need better understanding of whether this is correct??!?!!					// @@ i.e., we should just start a whole new shape here, right?					m_paths.push_back(path());					m_paths.back().m_new_shape = true;					fill_base = m_fill_styles.size();					line_base = m_line_styles.size();					read_fill_styles(&m_fill_styles, in, tag_type, m);					read_line_styles(&m_line_styles, in, tag_type);					num_fill_bits = in->read_uint(4);					num_line_bits = in->read_uint(4);				}			}			else			{				// EDGERECORD				int	edge_flag = in->read_uint(1);				if (edge_flag == 0)				{					// curved edge					int num_bits = 2 + in->read_uint(4);					float	cx = x + in->read_sint(num_bits);					float	cy = y + in->read_sint(num_bits);					float	ax = cx + in->read_sint(num_bits);					float	ay = cy + in->read_sint(num_bits);					if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg("  shape_character read: curved edge   = %4g %4g - %4g %4g - %4g %4g\n", x, y, cx, cy, ax, ay));					current_path.m_edges.push_back(edge(cx, cy, ax, ay));					x = ax;					y = ay;				}				else				{					// straight edge					int	num_bits = 2 + in->read_uint(4);					int	line_flag = in->read_uint(1);					float	dx = 0, dy = 0;					if (line_flag)					{						// General line.						dx = (float) in->read_sint(num_bits);						dy = (float) in->read_sint(num_bits);					}					else					{						int	vert_flag = in->read_uint(1);						if (vert_flag == 0) {							// Horizontal line.							dx = (float) in->read_sint(num_bits);						} else {							// Vertical line.							dy = (float) in->read_sint(num_bits);						}					}					if (SHAPE_LOG) IF_VERBOSE_PARSE(log_msg("  shape_character_read: straight edge = %4g %4g - %4g %4g\n", x, y, x + dx, y + dy));					current_path.m_edges.push_back(edge(x + dx, y + dy, x + dx, y + dy));					x += dx;					y += dy;				}			}		}	}	void	shape_character_def::display(character* inst)	// Draw the shape using our own inherent styles.	{		matrix	mat = inst->get_world_matrix();		cxform	cx = inst->get_world_cxform();		float	pixel_scale = inst->get_parent()->get_pixel_scale();		display(mat, cx, pixel_scale, m_fill_styles, m_line_styles);	}#ifdef DEBUG_DISPLAY_SHAPE_PATHS#include "base/ogl.h"	static void	point_normalize(point* p)	{		float	mag2 = p->m_x * p->m_x + p->m_y * p->m_y;		if (mag2 < 1e-9f)		{			// Very short vector.			// @@ log error			// Arbitrary unit vector.			p->m_x = 1;			p->m_y = 0;		}		float	inv_mag = 1.0f / sqrtf(mag2);		p->m_x *= inv_mag;		p->m_y *= inv_mag;	}	static void	show_fill_number(const point& p, int fill_number)	{		// We're inside a glBegin(GL_LINES)		// Eh, let's do it in binary, least sig four bits...		float	x = p.m_x;		float	y = p.m_y;		int	mask = 8;		while (mask)		{			if (mask & fill_number)			{				// Vert line --> 1.				glVertex2f(x, y - 40.0f);				glVertex2f(x, y + 40.0f);			}			else			{				// Rectangle --> 0.				glVertex2f(x - 10.0f, y - 40.0f);				glVertex2f(x + 10.0f, y - 40.0f);				glVertex2f(x + 10.0f, y - 40.0f);				glVertex2f(x + 10.0f, y + 40.0f);				glVertex2f(x - 10.0f, y + 40.0f);				glVertex2f(x + 10.0f, y + 40.0f);				glVertex2f(x - 10.0f, y - 40.0f);				glVertex2f(x - 10.0f, y + 40.0f);			}			x += 40.0f;			mask >>= 1;		}	}	static void	debug_display_shape_paths(		const matrix& mat,		float object_space_max_error,		const array<path>& paths,		const array<fill_style>& fill_styles,		const array<line_style>& line_styles)	{		for (int i = 0; i < paths.size(); i++)		{//			if (i > 0) break;//xxxxxxxx			const path&	p = paths[i];			if (p.m_fill0 == 0 && p.m_fill1 == 0)			{				continue;			}			gameswf::render::set_matrix(mat);			// Color the line according to which side has			// fills.			if (p.m_fill0 == 0) glColor4f(1, 0, 0, 0.5);			else if (p.m_fill1 == 0) glColor4f(0, 1, 0, 0.5);			else glColor4f(0, 0, 1, 0.5);			// Offset according to which loop we are.			float	offset_x = (i & 1) * 80.0f;			float	offset_y = ((i & 2) >> 1) * 80.0f;			glMatrixMode(GL_MODELVIEW);			glPushMatrix();			glTranslatef(offset_x, offset_y, 0.f);			point	pt;			glBegin(GL_LINE_STRIP);			mat.transform(&pt, point(p.m_ax, p.m_ay));			glVertex2f(pt.m_x, pt.m_y);			for (int j = 0; j < p.m_edges.size(); j++)			{				mat.transform(&pt, point(p.m_edges[j].m_cx, p.m_edges[j].m_cy));				glVertex2f(pt.m_x, pt.m_y);				mat.transform(&pt, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));				glVertex2f(pt.m_x, pt.m_y);			}			glEnd();			// Draw arrowheads.			point	dir, right, p0, p1;			glBegin(GL_LINES);			{for (int j = 0; j < p.m_edges.size(); j++)			{				mat.transform(&p0, point(p.m_edges[j].m_cx, p.m_edges[j].m_cy));				mat.transform(&p1, point(p.m_edges[j].m_ax, p.m_edges[j].m_ay));				dir = point(p1.m_x - p0.m_x, p1.m_y - p0.m_y);				point_normalize(&dir);				right = point(-dir.m_y, dir.m_x);	// perpendicular				const float	ARROW_MAG = 60.f;	// TWIPS?				if (p.m_fill0 != 0)				{					glColor4f(0, 1, 0, 0.5);					glVertex2f(p0.m_x,						   p0.m_y);					glVertex2f(p0.m_x - dir.m_x * ARROW_MAG - right.m_x * ARROW_MAG,						   p0.m_y - dir.m_y * ARROW_MAG - right.m_y * ARROW_MAG);					show_fill_number(point(p0.m_x - right.m_x * ARROW_MAG * 4,							       p0.m_y - right.m_y * ARROW_MAG * 4),							 p.m_fill0);				}				if (p.m_fill1 != 0)				{					glColor4f(1, 0, 0, 0.5);					glVertex2f(p0.m_x,						   p0.m_y);					glVertex2f(p0.m_x - dir.m_x * ARROW_MAG + right.m_x * ARROW_MAG,						   p0.m_y - dir.m_y * ARROW_MAG + right.m_y * ARROW_MAG);					show_fill_number(point(p0.m_x + right.m_x * ARROW_MAG * 4,							       p0.m_y + right.m_y * ARROW_MAG * 4),							 p.m_fill1);				}			}}			glEnd();			glPopMatrix();		}	}#endif // DEBUG_DISPLAY_SHAPE_PATHS			void	shape_character_def::display(		const matrix& mat,		const cxform& cx,		float pixel_scale,		const array<fill_style>& fill_styles,		const array<line_style>& line_styles) const	// Display our shape.  Use the fill_styles arg to	// override our default set of fill styles (e.g. when	// rendering text).	{		// Compute the error tolerance in object-space.		float	max_scale = mat.get_max_scale();		if (fabsf(max_scale) < 1e-6f)		{			// Scale is essentially zero.			return;		}		float	object_space_max_error = 20.0f / max_scale / pixel_scale * s_curve_max_pixel_error;#ifdef DEBUG_DISPLAY_SHAPE_PATHS		// Render a debug view of shape path outlines, instead		// of the tesselated shapes themselves.		if (gameswf_debug_show_paths)		{			debug_display_shape_paths(mat, object_space_max_error, m_paths, fill_styles, line_styles);			return;		}#endif // DEBUG_DISPLAY_SHAPE_PATHS		// See if we have an acceptable mesh available; if so then render with it.		for (int i = 0, n = m_cached_meshes.size(); i < n; i++)		{			const mesh_set*	candidate = m_cached_meshes[i];			if (object_space_max_error > candidate->get_error_tolerance() * 3.0f)			{				// Mesh is too high-res; the remaining meshes are higher res,				// so stop searching and build an appropriately scaled mesh.				break;			}			if (object_space_max_error > candidate->get_error_tolerance())			{				// Do it.				candidate->display(mat, cx, fill_styles, line_styles);				return;			}		}		// Construct a new mesh to handle this error tolerance.		mesh_set*	m = new mesh_set(this, object_space_max_error * 0.75f);		m_cached_meshes.push_back(m);		m->display(mat, cx, fill_styles, line_styles);				sort_and_clean_meshes();	}	static int	sort_by_decreasing_error(const void* A, const void* B)	{		const mesh_set*	a = *(const mesh_set**) A;		const mesh_set*	b = *(const mesh_set**) B;		if (a->get_error_tolerance() < b->get_error_tolerance())		{			return 1;		}		else if (a->get_error_tolerance() > b->get_error_tolerance())		{			return -1;		}		else		{			return 0;		}	}	void	shape_character_def::sort_and_clean_meshes() const	// Maintain cached meshes.  Clean out mesh_sets that haven't	// been used recently, and make sure they're sorted from high	// error to low error.	{		// Re-sort.		if (m_cached_meshes.size() > 0)		{			qsort(				&m_cached_meshes[0],				m_cached_meshes.size(),				sizeof(m_cached_meshes[0]),				sort_by_decreasing_error);			// Check to make sure the sort worked as intended.			#ifndef NDEBUG			for (int i = 0, n = m_cached_meshes.size() - 1; i < n; i++)			{				const mesh_set*	a = m_cached_meshes[i];				const mesh_set*	b = m_cached_meshes[i + 1];				assert(a->get_error_tolerance() > b->get_error_tolerance());			}			#endif // not NDEBUG		}	}			void	shape_character_def::tesselate(float error_tolerance, tesselate::trapezoid_accepter* accepter) const	// Push our shape data through the tesselator.	{		tesselate::begin_shape(accepter, error_tolerance);		for (int i = 0; i < m_paths.size(); i++)		{			if (m_paths[i].m_new_shape == true)			{				// Hm; should handle separate sub-shapes in a less lame way.				tesselate::end_shape();				tesselate::begin_shape(accepter, error_tolerance);			}			else			{				m_paths[i].tesselate();			}		}		tesselate::end_shape();	}	bool	shape_character_def::point_test_local(float x, float y)	// Return true if the specified point is on the interior of our shape.	// Incoming coords are local coords.	{		if (m_bound.point_test(x, y) == false)		{			// Early out.			return false;		}		// Try each of the paths.		for (int i = 0; i < m_paths.size(); i++)		{			if (m_paths[i].point_test(x, y))			{				return true;			}		}		return false;	}	float shape_character_def::get_height_local()	{		return m_bound.height();	}	float shape_character_def::get_width_local()	{		return m_bound.width();	}	void	shape_character_def::compute_bound(rect* r) const	// Find the bounds of this shape, and store them in	// the given rectangle.	{		r->m_x_min = 1e10f;		r->m_y_min = 1e10f;		r->m_x_max = -1e10f;		r->m_y_max = -1e10f;		for (int i = 0; i < m_paths.size(); i++)		{			const path&	p = m_paths[i];			r->expand_to_point(p.m_ax, p.m_ay);			for (int j = 0; j < p.m_edges.size(); j++)			{				r->expand_to_point(p.m_edges[j].m_ax, p.m_edges[j].m_ay);//					r->expand_to_point(p.m_edges[j].m_cx, p.m_edges[j].m_cy);			}		}	}	void	shape_character_def::output_cached_data(tu_file* out, const cache_options& options)	// Dump our precomputed mesh data to the given stream.	{		int	n = m_cached_meshes.size();		out->write_le32(n);		for (int i = 0; i < n; i++)		{			m_cached_meshes[i]->output_cached_data(out);		}	}	void	shape_character_def::input_cached_data(tu_file* in)	// Initialize our mesh data from the given stream.	{		int	n = in->read_le32();		m_cached_meshes.resize(n);		for (int i = 0; i < n; i++)		{			mesh_set*	ms = new mesh_set();			ms->input_cached_data(in);			m_cached_meshes[i] = ms;		}	}	}	// 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 + -