📄 smil_layout.cpp
字号:
rootrgn = m_surface_factory->new_topsurface(rn, bgrenderer, wf); m_rootsurfaces.push_back(rootrgn); return rootrgn;}region_node *smil_layout_manager::get_region_node_for(const lib::node *n, bool nodeoverride){ if (nodeoverride) { std::map<const lib::node*, region_node*>::size_type count = m_node2region.count(n); if (count) { AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_surface(): per-node override"); return (*m_node2region.find(n)).second; } } const char *prname = NULL; if (n->get_local_name() == "a" && n->down()) { // XXX This is not 100% correct: it does not take subregion positioning into account prname = n->down()->get_attribute("region"); } else if (n->get_local_name() == "area" && n->up()) { // XXX This is not 100% correct: it does not take subregion positioning into account prname = n->up()->get_attribute("region"); } else { prname = n->get_attribute("region"); } const char *nid = n->get_attribute("id"); if (prname == NULL) { AM_DBG lib::logger::get_logger()->debug( "smil_layout_manager::get_surface(): no region attribute on %s", (nid?nid:"")); return NULL; } std::string rname = prname; std::map<std::string, std::list<region_node*> >::iterator rit = m_name2region.find(rname); std::map<std::string, region_node*>::size_type namecount = (rit == m_name2region.end())?0:(*rit).second.size(); if (namecount > 1) lib::logger::get_logger()->trace("smil_layout_manager::get_surface(): Using first region %s only", prname); if (namecount > 0) { AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_surface(): matched %s by regionName", prname); return (*m_name2region.find(rname)).second.front(); } std::multimap<std::string, region_node*>::size_type idcount = m_id2region.count(rname); if (idcount > 0) { AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_surface(): matched %s by id", prname); return m_id2region[rname]; } AM_DBG lib::logger::get_logger()->debug("smil_layout_manager::get_surface(): no match for %s", prname); return NULL;}common::surface *smil_layout_manager::get_surface(const lib::node *n) { region_node *rn = get_region_node_for(n, true); if (rn == NULL) { AM_DBG lib::logger::get_logger()->debug("get_surface: returning default region for 0x%x", (void*)n); return get_default_rendering_surface(n); } common::surface_template *stemp = rn->get_surface_template(); if (stemp == NULL) { lib::logger::get_logger()->debug("Internal error: get_surface: region found, but no surface, node=0x%x, rn=0x%x", (void*)n, (void*)rn); lib::logger::get_logger()->error(gettext("Programmer error encountered, attempting to continue")); return get_default_rendering_surface(n); } common::surface *surf = stemp->activate(); return surf;}common::surface_template *smil_layout_manager::get_region(const lib::node *n) { region_node *rn = get_region_node_for(n, true); return rn?rn->get_surface_template():NULL;}common::animation_notification *smil_layout_manager::get_animation_notification(const lib::node *n) { region_node *rn = get_region_node_for(n, true); return rn?rn->get_animation_notification():NULL;}common::animation_destination *smil_layout_manager::get_animation_destination(const lib::node *n) { region_node *rn = get_region_node_for(n, true); return rn?rn->get_animation_destination():NULL;}// Helper function: decode pre-defined repoint namesstatic booldecode_regpoint(common::regpoint_spec &pt, const char *name){ if(!name || !name[0] || strcmp(name, "topLeft") == 0) pt = common::regpoint_spec(0.0, 0.0); else if (strcmp(name, "topMid") == 0) pt = common::regpoint_spec(0.5, 0.0); else if (strcmp(name, "topRight") == 0) pt = common::regpoint_spec(1.0, 0.0); else if (strcmp(name, "midLeft") == 0) pt = common::regpoint_spec(0.0, 0.5); else if (strcmp(name, "center") == 0) pt = common::regpoint_spec(0.5, 0.5); else if (strcmp(name, "midRight") == 0) pt = common::regpoint_spec(1.0, 0.5); else if (strcmp(name, "bottomLeft") == 0) pt = common::regpoint_spec(0.0, 1.0); else if (strcmp(name, "bottomMid") == 0) pt = common::regpoint_spec(0.5, 1.0); else if (strcmp(name, "bottomRight") == 0) pt = common::regpoint_spec(1.0, 1.0); else return false; return true;}// Helper function: get region_dim value from an attributestatic common::region_dimget_regiondim_attr(const lib::node *rn, char *attrname){ const char *attrvalue = rn->get_attribute(attrname); common::region_dim rd; if (attrvalue == NULL || *attrvalue == '\0') { // pass: region_dim are initialized as auto } else { int ivalue; char *endptr; ivalue = strtol(attrvalue, &endptr, 10); if (*endptr == '\0' || strcmp(endptr, "px") == 0) { rd = ivalue; } else if (*endptr == '%') { double fvalue; fvalue = ivalue / 100.0; rd = fvalue; } else { lib::logger::get_logger()->trace("%s: cannot parse %s=\"%s\"", rn->get_sig().c_str(), attrname, attrvalue); lib::logger::get_logger()->warn(gettext("Syntax error in SMIL document")); } } return rd;}common::alignment *smil_layout_manager::get_alignment(const lib::node *n){ const char *regPoint; const char *regAlign; const char *rpname = "regPoint"; const char *raname = "regAlign"; regPoint = n->get_attribute("regPoint"); regAlign = n->get_attribute("regAlign"); const char *mediaAlign = n->get_attribute("mediaAlign"); if (mediaAlign && regPoint == NULL) { regPoint = mediaAlign; rpname = "mediaAlign"; } if (mediaAlign && regAlign == NULL) { regAlign = mediaAlign; raname = "mediaAlign"; } if (regPoint == NULL || regAlign == NULL) { const region_node *rrn = get_region_node_for(n, false); if (rrn == NULL) return NULL; const lib::node *rn = rrn->dom_node(); if (regPoint == NULL) { regPoint = rn->get_attribute("regPoint"); // XXXX this means mediaAlign overrides regPoint/regAlign, which is open to discussion if (regPoint == NULL) regPoint = rn->get_attribute("mediaAlign"); } if (regAlign == NULL) { regAlign = rn->get_attribute("regAlign"); // XXXX this means mediaAlign overrides regPoint/regAlign, which is open to discussion if (regAlign == NULL) regAlign = rn->get_attribute("mediaAlign"); } } if (regPoint == NULL && regAlign == NULL) return NULL; common::regpoint_spec image_fixpoint = common::regpoint_spec(0, 0); common::regpoint_spec surface_fixpoint = common::regpoint_spec(0, 0); lib::node *regpoint_node = NULL; if (!decode_regpoint(surface_fixpoint, regPoint) && regPoint != NULL) { // Non-standard regpoint. Look it up. std::map<std::string, lib::node*>::iterator it = m_id2regpoint.find(regPoint); if (it == m_id2regpoint.end()) { lib::logger::get_logger()->trace("%s: unknown %s value: %s", n->get_sig().c_str(), rpname, regPoint); lib::logger::get_logger()->warn(gettext("Syntax error in SMIL document")); } else { regpoint_node = (*it).second; // XXX Just for now:-) surface_fixpoint.left = get_regiondim_attr(regpoint_node, "left"); surface_fixpoint.top = get_regiondim_attr(regpoint_node, "top"); } } if (!decode_regpoint(image_fixpoint, regAlign)) { // See if we can get one from the regPoint node, if there is one bool found = false; if (regpoint_node) { const char *regPointAlign = regpoint_node->get_attribute("regAlign"); if (decode_regpoint(image_fixpoint, regPointAlign)) found = true; } if (!found && regAlign != NULL) { lib::logger::get_logger()->trace("%s: unknown %s value: %s", n->get_sig().c_str(), raname, regAlign); lib::logger::get_logger()->warn(gettext("Syntax error in SMIL document")); } } return new common::smil_alignment(image_fixpoint, surface_fixpoint);}common::surface *smil_layout_manager::get_default_rendering_surface(const lib::node *n) { const char *nid = n->get_attribute("id"); lib::logger::get_logger()->trace("Returning default rendering surface for node %s", (nid?nid:"")); return m_rootsurfaces[0]->activate();}class bgimage_loader : public lib::ref_counted_obj, public common::playable_notification { public: bgimage_loader(const lib::node *layout_root, common::factories *factories); ~bgimage_loader(); void run(smil_layout_manager *layout_mgr); /// playable_notification interface: void started(cookie_type n, double t = 0) {}; void stopped(cookie_type n, double t = 0); void stalled(cookie_type n, double t = 0) {}; void unstalled(cookie_type n, double t = 0) {}; void clicked(cookie_type n, double t = 0) {}; void pointed(cookie_type n, double t = 0) {}; void transitioned(cookie_type n, double t = 0) {}; private: const lib::node *m_layout_root; common::factories *m_factories; lib::timer_control *m_timer; lib::event_processor *m_event_processor; std::vector<lib::node*> m_nodes; std::map<int, common::playable*> m_playables; std::vector<common::playable*> m_old_playables; std::set<common::gui_window*> m_gui_windows; lib::critical_section m_lock; lib::condition m_condition;};voidsmil_layout_manager::load_bgimages(common::factories *factories){// if (!m_uses_bgimages) return;// abort(); if (!m_layout_section || !m_uses_bgimages) return; bgimage_loader *loader = new bgimage_loader(m_layout_section, factories); loader->run(this); loader->release();}bgimage_loader::bgimage_loader(const lib::node *layout_root, common::factories *factories): m_layout_root(layout_root), m_factories(factories), m_timer(new lib::timer_control_impl(lib::realtime_timer_factory(), 1.0, false)), m_event_processor(NULL){ m_event_processor = event_processor_factory(m_timer);}bgimage_loader::~bgimage_loader(){ m_lock.enter(); std::set<common::gui_window*>::iterator iw; AM_DBG lib::logger::get_logger()->debug("bgimage_loader::~bgimage_loader(): sync redraw"); for (iw=m_gui_windows.begin(); iw != m_gui_windows.end(); iw++) (*iw)->redraw_now(); AM_DBG lib::logger::get_logger()->debug("bgimage_loader::~bgimage_loader(): delete playables"); std::vector<common::playable*>::iterator ip; for (ip=m_old_playables.begin(); ip != m_old_playables.end(); ip++) { (*ip)->stop(); (*ip)->release(); } AM_DBG lib::logger::get_logger()->debug("bgimage_loader::~bgimage_loader(): delete nodes"); std::vector<lib::node*>::iterator in; for (in=m_nodes.begin(); in != m_nodes.end(); in++) delete *in; AM_DBG lib::logger::get_logger()->debug("bgimage_loader::~bgimage_loader(): delete event processor"); delete m_event_processor; delete m_timer; m_lock.leave();}voidbgimage_loader::run(smil_layout_manager *layout_mgr){ m_lock.enter(); AM_DBG lib::logger::get_logger()->debug("load_bgimages: loading background images"); // XXX Create an event_processor // Loop over the layout section, starting the renderers as we find regions that // want a background image. lib::node::const_iterator it; lib::node::const_iterator end = m_layout_root->end(); const lib::node_context *context = m_layout_root->get_context(); for(it = m_layout_root->begin(); it != end; it++) { if (!(*it).first) continue; const lib::node *rn = (*it).second; if (rn->get_attribute("backgroundImage") == NULL) continue; common::surface *surf = layout_mgr->get_surface(rn); if (!surf) { lib::logger::get_logger()->debug("bgimage_loader: no surface"); continue; } const char *bgimage = surf->get_info()->get_bgimage(); if (!bgimage) continue; const char *bgrepeat = rn->get_attribute("backgroundRepeat"); AM_DBG lib::logger::get_logger()->debug("load_bgimages: load bgimage %s", bgimage); const char *attrs[9], **attrp = attrs; *attrp++ = "src"; *attrp++ = bgimage; *attrp++ = "backgroundImage"; *attrp++ = bgimage; *attrp++ = "erase"; *attrp++ = "never"; if (bgrepeat) { *attrp++ = "backgroundRepeat"; *attrp++ = bgrepeat; } *attrp++ = NULL; lib::node *n = m_factories->get_node_factory()->new_node("img", attrs, context); // Create the renderer if (n) { cookie_type p_index = (cookie_type)m_playables.size(); common::playable *p = m_factories->get_playable_factory()->new_playable(this, p_index, n, m_event_processor); if (p) { // Now tell the renderer where to render to, and remember the // toplevel gui_window so we can synchronise the redraws before // zapping the whole bgimage_loader and other objects. common::renderer *r = p->get_renderer(); if (r) { r->set_surface(surf); common::gui_window *w = surf->get_gui_window(); if (w && !m_gui_windows.count(w)) m_gui_windows.insert(w); } else { lib::logger::get_logger()->debug("bgimage_loader: no renderer"); } // Remember renderer and node. m_nodes.push_back(n); m_playables[p_index] = p; // And start it m_lock.leave(); p->start(0); m_lock.enter(); } else { delete n; } } } if (m_playables.size()) { // All the renderers are started. Wait for everything to finish. AM_DBG lib::logger::get_logger()->debug("bgimage_loader::run: waiting for %d renderers", m_playables.size()); m_lock.leave(); m_condition.wait(-1, m_lock); } m_lock.leave();}voidbgimage_loader::stopped(cookie_type n, double t){ AM_DBG lib::logger::get_logger()->debug("bgimage_loader::stopped() called"); m_lock.enter(); if (m_playables.count(n) > 0) { common::playable *p = m_playables[n]; m_old_playables.push_back(p); m_playables.erase(n); if (m_playables.size() == 0) { AM_DBG lib::logger::get_logger()->debug("bgimage_loader::stopped: signalling condition"); m_condition.signal(); } else { AM_DBG lib::logger::get_logger()->debug("bgimage_loader::stopped: %d more renderers", m_playables.size()); } } m_lock.leave();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -