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

📄 timegraph.cpp

📁 彩信浏览器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// This file is part of Ambulant Player, www.ambulantplayer.org.//// Copyright (C) 2003-2007 Stichting CWI, // Kruislaan 413, 1098 SJ Amsterdam, The Netherlands.//// Ambulant Player is free software; you can redistribute it and/or modify// it under the terms of the GNU Lesser General Public License as published by// the Free Software Foundation; either version 2.1 of the License, or// (at your option) any later version.//// Ambulant Player is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public License// along with Ambulant Player; if not, write to the Free Software// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA/*  * @$Id: timegraph.cpp,v 1.24 2007/02/12 14:15:23 jackjansen Exp $  */#include "ambulant/lib/document.h"#include "ambulant/lib/node.h"#include "ambulant/lib/logger.h"#include "ambulant/common/schema.h"#include "ambulant/smil2/timegraph.h"#include "ambulant/smil2/time_node.h"#include "ambulant/smil2/animate_n.h"#include "ambulant/smil2/time_attrs.h"#include "ambulant/smil2/test_attrs.h"#include "ambulant/smil2/sync_rule.h"#include <cmath>#include <stack>#include <cstdlib>//#define AM_DBG if(1)#ifndef AM_DBG#define AM_DBG if(0)#endifusing namespace ambulant;using namespace smil2;timegraph::timegraph(time_node::context_type *ctx, const document *doc, const schema *sch) :	m_context(ctx),	m_schema(sch),	m_root(0),	m_dom2tn(0) {	assert(doc!=0);	assert(sch!=0);	m_logger = lib::logger::get_logger();	m_dom2tn = new std::map<int, time_node*>();	m_root = build_time_tree(doc->get_root());	AM_DBG m_logger->debug("Time nodes created: %d", time_node::get_node_counter());	build_priorities();	build_time_graph();	build_timers_graph();	build_trans_out_graph();}timegraph::~timegraph() {	if(m_root) {		delete m_root;		AM_DBG m_logger->debug("Undeleted time nodes: %d", time_node::get_node_counter());	} // else detached	if(m_dom2tn)		delete m_dom2tn;}time_node* timegraph::detach_root() {	time_node* tmp = m_root;	m_root = 0;	return tmp;}std::map<int, time_node*>* timegraph::detach_dom2tn() {	std::map<int, time_node*>* tmp = m_dom2tn;	m_dom2tn = 0;	return tmp;}time_node* timegraph::build_time_tree(const lib::node *root) {	const std::set<std::string>& te = m_schema->get_time_elements();	time_node *time_root = 0;	std::stack<time_node*> stack;	std::stack<const lib::node*> switch_stack;	std::stack<const lib::node*> select_stack;	lib::node::const_iterator it;	lib::node::const_iterator end = root->end();	int localIdCounter = 1;	for(it = root->begin(); it != end; it++) {		std::pair<bool, const lib::node*> pair = *it;		bool start_element = pair.first;		const lib::node *n = pair.second;		const std::string& tag = n->get_local_name();				// keep switch tree ref		if(tag == "switch") {			if(start_element) {				switch_stack.push(n);				select_stack.push(select_switch_child(n));			} else  {				switch_stack.pop();				select_stack.pop();			}		} 		// <a actuate="onLoad"/> we treat as area. This is not pretty, but it		// works.		bool is_onload_a = false;		if (tag == "a" && n->down() == NULL) {			const char *actuate = n->get_attribute("actuate");			if (actuate && strcmp(actuate, "onLoad") == 0)				is_onload_a = true;		}		// if not a time element then continue to next		if(te.find(tag) == te.end() && !is_onload_a) continue;				// when within a switch and not selected then continue to next		if(!switch_stack.empty() && (select_stack.top() == 0 ||			!const_nnhelper::is_descendent(n, select_stack.top()))) {			// skip node content			it++;			while((*it).second != n) it++;			continue;		}		// support inline tests		test_attrs ta(n);		if(!ta.selected()) {			// skip content			AM_DBG m_logger->debug("Filtering out node: %s[%s]", 				ta.get_tag().c_str(), ta.get_id().c_str());			it++;			while((*it).second != n) it++;			continue;		}				if(start_element) {			// create a time node for each start element			time_node *tn = create_time_node(n, stack.empty()?0:stack.top());						// add 'a' parent as a child			if(n->up() && n->up()->get_local_name() == "a") {				time_node *tnp = create_time_node(n->up(), tn);				tn->append_child(tnp);				const char *pidp = n->get_attribute("id");				if(pidp) m_id2tn[pidp] = tn;			}						// read or create node id and add it the map			std::string ident;			const char *pid = n->get_attribute("id");			if(pid) ident = pid;			else {				ident += "aid";				char b[32];sprintf(b,"%u",localIdCounter++);				ident += b;			}			m_id2tn[ident] = tn;						if(stack.empty()) {				assert(time_root == 0);				time_root = tn;			} else {				// container or media with area or animate elements, etc				stack.top()->append_child(tn);			}			stack.push(tn);		} else {			stack.pop();		}	}	return time_root;}time_node* timegraph::create_time_node(const node* n, time_node* tparent) const {	time_node *tn = 0;	time_container_type tct =		m_schema->get_time_type(n->get_qname());	if(tct == tc_seq) 		tn = new seq(m_context, n);	else if(tct == tc_par) 		tn = new par(m_context, n);	else if(tct == tc_excl) 		tn = new excl(m_context, n);	else if(m_schema->is_animation(n->get_qname())) 		tn = animate_node::new_instance(m_context, n, tparent->dom_node());	else 		tn = new time_node(m_context, n, tc_none, m_schema->is_discrete(n->get_qname()));	(*m_dom2tn)[n->get_numid()] = tn;	return tn;}void timegraph::build_time_graph() {	time_node::iterator it;	time_node::iterator end = m_root->end();	for(it = m_root->begin(); it != end; it++) {		if(!(*it).first) continue;		time_node *tn = (*it).second;		add_begin_sync_rules(tn);		add_end_sync_rules(tn);		if(tn->is_link() && tn->get_time_attrs()->get_actuate() == actuate_onrequest) {			tn->set_want_activate_event(true);		}	}}void timegraph::build_priorities() {	time_node::iterator it;	time_node::iterator end = m_root->end();	for(it = m_root->begin(); it != end; it++) {		if(!(*it).first) continue;		time_node *tn = (*it).second;		if(tn->is_excl()) {			excl *e = qualify<excl*>(tn);			e->built_priorities();		}	}}// Builds the network of timers based on the sync behavior declared in the document// The spec allows many aspects to be implementation specific  // XXX: for now assume always "can slip sync behavior".void timegraph::build_timers_graph() {	if(!m_context->get_timer())		return; // not supported by context	time_node::iterator it;	time_node::iterator end = m_root->end();	for(it = m_root->begin(); it != end; it++) {		if(!(*it).first) continue;		time_node *tn = (*it).second;		lib::timer_control *timer = 0;		if(tn->is_root()) timer = new lib::timer_control_impl(m_context->get_timer(), 1.0, false);		else timer = new lib::timer_control_impl(tn->up()->get_timer(), 1.0, false);		tn->set_timer(timer);	}}// Adds sync rules for out transitionsvoid timegraph::build_trans_out_graph() {	time_node::iterator it;	time_node::iterator end = m_root->end();	for(it = m_root->begin(); it != end; it++) {		if(!(*it).first) continue;		time_node *tn = (*it).second;		const time_attrs *ta = tn->get_time_attrs();		if(!ta->get_trans_out()) continue;		time_type offset = -ta->get_trans_out_dur();		// We should now arrange so that the out transition 		// starts before the node is removed.

⌨️ 快捷键说明

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