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

📄 smil_layout.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: smil_layout.cpp,v 1.46 2007/02/12 14:15:15 jackjansen Exp $  */#include "ambulant/lib/logger.h"#include "ambulant/lib/node.h"#include "ambulant/lib/document.h"#include "ambulant/common/schema.h"#include "ambulant/common/region_dim.h"#include "ambulant/common/layout.h"#include "ambulant/common/preferences.h"#include "ambulant/common/smil_alignment.h"#include "ambulant/smil2/region_node.h"#include "ambulant/smil2/smil_layout.h"#include "ambulant/smil2/test_attrs.h"#include <stack>// #define AM_DBG#ifndef AM_DBG#define AM_DBG if(0)#endifusing namespace ambulant;using namespace smil2;// Factory functioncommon::layout_manager *common::create_smil2_layout_manager(common::factories *factory,lib::document *doc){	return new smil_layout_manager(factory, doc);}smil_layout_manager::smil_layout_manager(common::factories *factory,lib::document *doc):   m_schema(common::schema::get_instance()),	m_surface_factory(common::create_smil_surface_factory()),	m_layout_tree(NULL),	m_uses_bgimages(false){	// First find the correct layout section to use.	m_layout_section = get_document_layout(doc);	// Then scan the DOM tree and create our own tree of region_node objects	build_layout_tree(m_layout_section);		// Next we create the region_nodes for body nodes that need one (subregion	// positioning, etc)	build_body_regions(doc);	// Next, create the surfaces that correspond to this tree	build_surfaces(factory->get_window_factory());		// Now we make sure there is at least one root-layout. This allows us	// to use this as the default region. XXXX Should be auto-show eventually.	if (m_rootsurfaces.empty()) {		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: no rootLayouts, creating one");		create_top_surface(factory->get_window_factory(), NULL, NULL);	}}smil_layout_manager::~smil_layout_manager(){	m_schema = NULL;	std::vector<common::surface_template*>::iterator i;	for (i=m_rootsurfaces.begin(); i != m_rootsurfaces.end(); i++)		delete (*i);	// XXX Delete m_layout_tree tree	delete m_layout_tree;}lib::node *smil_layout_manager::get_document_layout(lib::document *doc){	// We first have to find the layout section in the tree	lib::node *doc_root = doc->get_root();	lib::node *head = doc_root->get_first_child("head");	if (!head) {		lib::logger::get_logger()->trace("smil_layout_manager: no <head> section");		return NULL;	}	lib::node *layout_root = head->get_first_child("layout");	if (layout_root) {		// Check that the type is supported		const char *layout_type = layout_root->get_attribute("type");		if (layout_type && strcmp(layout_type, "text/smil-basic-layout") != 0 ) {			lib::logger::get_logger()->trace("smil_layout_manager: <layout type=\"%s\"> not supported", layout_type);			lib::logger::get_logger()->warn(gettext("Problem with layout in SMIL document"));			return NULL;		}		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: returning node 0x%x", layout_root);		return layout_root;	}	// Otherwise check for a switch	lib::node *layout_switch = head->get_first_child("switch");	AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: examining <switch>");	if (layout_switch) {		layout_root = layout_switch->down();		while (layout_root) {			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: examining node 0x%x", layout_root);			// Check that it is indeed a <layout> node			if (m_schema->get_layout_type((layout_root)->get_qname()) != common::l_layout) {				lib::logger::get_logger()->trace("smil_layout_manager: <switch> in <head> should contain only <layout>s");				lib::logger::get_logger()->warn(gettext("Problem with layout in SMIL document"));				continue;			}			// Check that the type is supported			const char *layout_type = layout_root->get_attribute("type");			if (layout_type && strcmp(layout_type, "text/smil-basic-layout") != 0 ) {				lib::logger::get_logger()->trace("smil_layout_manager: <layout type=\"%s\"> not supported, skipping", layout_type);				continue;			}			test_attrs *tester = new test_attrs(layout_root);			if (tester->selected()) {				delete tester;				AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: returning node 0x%x", layout_root);				return layout_root;			}			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: skipping layout section due to test attributes");			delete tester;			layout_root = layout_root->next();		}	}		lib::logger::get_logger()->warn(gettext("Problem with layout in SMIL document"));	return NULL;}voidsmil_layout_manager::build_layout_tree(lib::node *layout_root){	std::stack<region_node *> stack;	// Now we iterate over all the elements, set their dimensions	// from the attributes and determine their inheritance	lib::node::iterator it;	lib::node::iterator end = layout_root->end();	int level = -1;	for(it = layout_root->begin(); it != end; it++) {		std::pair<bool, lib::node*> pair = *it;		if (pair.first) {			level++;			//if (level == 0) continue; // Skip layout section itself			lib::node *n = pair.second;			const char *pid = n->get_attribute("id");			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_document_layout: examining %s %s", 				n->get_qname().second.c_str(), (pid?pid:"no-id"));			// Find node type			common::layout_type tp = m_schema->get_layout_type(n->get_qname());			// First we handle regPoint nodes, which we only store			if (tp == common::l_regpoint) {				if (pid) {					std::string id = pid;					m_id2regpoint[id] = n;				} else {					lib::logger::get_logger()->trace("smil_layout_manager: regPoint node without id attribute");				}				continue;			}			dimension_inheritance di;			if (tp == common::l_rootlayout || tp == common::l_toplayout) {				di = di_none;			} else if (level == 1) {				// Toplevel region node				di = di_rootlayout;			} else {				// lower-level region node				di = di_parent;			}			// Put it in the tree			region_node *rn = new region_node(n, di);			rn->reset();			if (stack.empty()) {				AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_document_layout: 0x%x is m_layout_tree", (void*)rn);				if(m_layout_tree != NULL) {					lib::logger::get_logger()->error("smil_layout_manager: multiple layout roots!");				}				m_layout_tree = rn;			} else {				region_node *parent = stack.top();				parent->append_child(rn);				AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_document_layout: 0x%x is child of 0x%x", (void*)rn, (void*)parent);			}			// Enter the region ID into the id-mapping			if(pid) {				std::string id = pid;				AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: mapping id %s", pid);				m_id2region[id] = rn;			}						// And the same for the regionName multimap			const char *pname = n->get_attribute("regionName");			if(pname) {				AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: mapping regionName %s", pname);				m_name2region[pname].push_back(rn);			}						// See if the node uses background images			if (n->get_attribute("backgroundImage")) m_uses_bgimages = true;			// And finally into the node->region mapping (for animate)			m_node2region[n] = rn;			stack.push(rn);		} else {			level--;			stack.pop();		}	}}voidsmil_layout_manager::build_body_regions(lib::document *doc) {	// Finally we loop over the body nodes, and determine which ones need a region_node	// because they use subregion positioning, override background color, etc.	lib::node *doc_root = doc->get_root();	lib::node *body = doc_root->get_first_child("body");	if (!body) {		lib::logger::get_logger()->error(gettext("Document has no <body> section, nothing to play"));		return;	}	lib::node::const_iterator it;	lib::node::const_iterator end = body->end();	for(it = body->begin(); it != end; it++) {		std::pair<bool, const lib::node*> pair = *it;		if (!pair.first) continue;		const lib::node *n = pair.second;#ifdef OLD_SUBREGIONS				if (!region_node::needs_region_node(n)) continue;#else		if(!test_attrs(n).selected()) continue;		if(!n->get_attribute("region") && !region_node::needs_region_node(n) &&			n->get_local_name() != "area") continue;#endif		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_body_regions: region for 0x%x %s", (void*)n, n->get_local_name().c_str());		region_node *rn = new region_node(n, di_parent);		region_node *parent = get_region_node_for(n, false);		if (parent) rn->fix_from_region_node(parent);		rn->reset();		rn->set_showbackground(false);		rn->set_as_subregion(true);		if (!parent) {			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: subregion positioning on default region, node=0x%x, rn=0x%x", (void*)n, (void*)rn);			m_default_region_subregions.push_back(rn);		} else {			parent->append_child(rn);		}		m_node2region[n] = rn;	}}	voidsmil_layout_manager::build_surfaces(common::window_factory *wf) {	std::stack<common::surface_template*> stack;	region_node::iterator it;	region_node::const_iterator end = m_layout_tree->end();		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces called");	assert(wf);	// First we check for a root-layout node. This will be used as the parent	// of toplevel region nodes. If there is no root-layout but there are	// toplevel region nodes we will create it later.	common::surface_template *root_surface = NULL;	region_node *first_root_layout = m_layout_tree ? m_layout_tree->get_first_child("root-layout") : NULL;	if (first_root_layout) {		common::bgrenderer *bgrenderer = wf->new_background_renderer(first_root_layout);		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces: create root_layout");		root_surface = create_top_surface(wf, first_root_layout, bgrenderer);		assert(root_surface);		first_root_layout->set_surface_template(root_surface);	}			// Loop over all the layout elements, create the regions and root_layouts,	// and keep a stack to tie everything together.	if (m_layout_tree) {		for(it = m_layout_tree->begin(); it != end; it++) {			std::pair<bool, region_node*> pair = *it;			region_node *rn = pair.second;			const lib::node *n = rn->dom_node();			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager: examining %s node 0x%x", n->get_qname().second.c_str(), rn);			common::layout_type tag = m_schema->get_layout_type(n->get_qname());			if(tag == common::l_rootlayout) {				continue;			}			if (tag == common::l_layout)				continue;			if (tag == common::l_none ) {				// XXXX Will need to handle switch here too				// Assume subregion positioning.				AM_DBG lib::logger::get_logger()->trace("smil_layout_manager: skipping <%s> in layout", n->get_qname().second.c_str());				continue;			}			if (tag == common::l_media) {				tag = common::l_region;			}			if (pair.first) {				// On the way down we create the regions and remember				// them				common::bgrenderer *bgrenderer = wf->new_background_renderer(rn);				common::surface_template *surf;				const char *pid = n->get_attribute("id");				std::string ident = "<unnamed>";				if(pid) {					ident = pid;				}				// Test that rootlayouts are correctly nested.				if (!stack.empty()) {					if (tag != common::l_region) {						lib::logger::get_logger()->trace("%s: topLayout element inside other element", n->get_sig().c_str());						lib::logger::get_logger()->error(gettext("Problem with layout in SMIL document"));						tag = common::l_region;					}				}				// Create the region or the root-layout				if (tag == common::l_toplayout) {						AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces: create topLayout");					surf = create_top_surface(wf, rn, bgrenderer);				} else if (tag == common::l_region && !stack.empty()) {					common::surface_template *parent = stack.top();					surf = parent->new_subsurface(rn, bgrenderer);				} else if (tag == common::l_region && stack.empty()) {					// Create root-layout if it doesn't exist yet					if (root_surface == NULL) {						AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces: create default root-layout");						root_surface = create_top_surface(wf, NULL, NULL);					}					surf = root_surface->new_subsurface(rn, bgrenderer);				} else {					assert(0);				}				// Store in the region_node				assert(surf); // XXXX Good idea?				rn->set_surface_template(surf);								// Finally push on to the stack for reference by child nodes				stack.push(surf);			} else {				// On the way back up we only need to pop the stack				stack.pop();			}		}	}	// Finally we create the regions for body regions that use subregion	// positioning on the default region	std::vector<region_node *>::iterator bit;	std::vector<region_node *>::const_iterator bend = m_default_region_subregions.end();	for (bit = m_default_region_subregions.begin(); bit != bend; bit++) {		region_node *rn = *bit;		common::bgrenderer *bgrenderer = wf->new_background_renderer(rn);		if (root_surface == NULL) {			AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces: create default root-layout for subregion positioning");			root_surface = create_top_surface(wf, NULL, NULL);		}		common::surface_template *surf = root_surface->new_subsurface(rn, bgrenderer);		assert(surf); // XXXX Good idea?		rn->set_surface_template(surf);		AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::build_surfaces: subregion 0x%x surface 0x%x", (void*)rn, (void*)surf);	}}common::surface_template *smil_layout_manager::create_top_surface(common::window_factory *wf, const region_node *rn, common::bgrenderer *bgrenderer){	common::surface_template *rootrgn;

⌨️ 快捷键说明

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