📄 animate_n.cpp
字号:
// 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: animate_n.cpp,v 1.21 2007/02/12 14:15:14 jackjansen Exp $ */#include "ambulant/smil2/animate_n.h"#include "ambulant/smil2/animate_f.h"#include "ambulant/lib/document.h"#include "ambulant/common/region_info.h"#include "ambulant/lib/colors.h"#include "ambulant/common/region_dim.h"#include "ambulant/lib/logger.h"//#define AM_DBG if(1)#ifndef AM_DBG#define AM_DBG if(0)#endif#define IGNORE_ATTR_COMP trueusing namespace ambulant;using namespace smil2;////////////////////////////////////// animate_node//// An animate_node is the base class for all animation node flavorsanimate_node::animate_node(context_type *ctx, const node *n, animate_attrs *aattrs): time_node(ctx, n, tc_none, false), m_aattrs(aattrs) {}animate_node::~animate_node() { delete m_aattrs;}void animate_node::prepare_interval() {}void animate_node::read_dom_value(common::animation_destination *dst, animate_registers& regs) const {}bool animate_node::set_animated_value(common::animation_destination *dst, animate_registers& regs) const { return false;}void animate_node::apply_self_effect(animate_registers& regs) const {}////////////////////////////////////// linear_values animation// A linear_values_animation is applicable for linear-attributes// linear-attributes define: addition, subtraction and scaling// A linear_values_animation may be continuous or discrete // The interpolation mode (calcMode) of a continuous linear_values animation may be linear, paced or spline// F: the simple function// T: the type of the attribute// The type T must define addition, subtraction and scalingtemplate <class F, class T>class linear_values_animation : public animate_node { public: linear_values_animation(context_type *ctx, const node *n, animate_attrs *aattrs); ~linear_values_animation(); void prepare_interval(); protected: bool verify_key_times(std::vector<double>& keyTimes); F m_simple_f; animate_f<F> *m_animate_f; std::vector<T> m_values; };template <class F, class T>linear_values_animation<F, T>::linear_values_animation(context_type *ctx, const node *n, animate_attrs *aattrs): animate_node(ctx, n, aattrs), m_animate_f(0) { m_aattrs->get_values(m_values);}template <class F, class T>linear_values_animation<F, T>::~linear_values_animation() { delete m_animate_f;}template <class F, class T>void linear_values_animation<F, T>::prepare_interval() { time_type dur = calc_dur(); time_type sfdur = dur; const time_attrs* ta = get_time_attrs(); if(dur.is_definite() && ta->auto_reverse()) sfdur /= 2; if(m_aattrs->get_calc_mode() == "paced") { // ignore key times m_simple_f.paced_init(sfdur(), m_values); } else { // use key times when valid and when not ignorable std::vector<double> keyTimes; m_aattrs->get_key_times(keyTimes);//gcc2.95 Internal compiler error in `assign_stack_temp_for_type `// bool keyTimesValid = keyTimes.empty() || verify_key_times(keyTimes); bool keyTimesValid = false; if(keyTimes.empty() || verify_key_times(keyTimes)) keyTimesValid = true; if(!keyTimes.empty() && keyTimesValid && (dur.is_definite() || m_aattrs->get_calc_mode() == "discrete")) { m_simple_f.init(sfdur(), m_values, keyTimes); } else m_simple_f.init(sfdur(), m_values); } m_simple_f.set_auto_reverse(ta->auto_reverse()); m_simple_f.set_accelerate(ta->get_accelerate(), ta->get_decelerate()); time_type ad = m_interval.end - m_interval.begin; m_animate_f = new animate_f<F>(m_simple_f, dur(), ad(), m_aattrs->is_accumulative());}template <class F, class T>bool linear_values_animation<F, T>::verify_key_times(std::vector<double>& keyTimes) { bool keyTimesValid = true; if(keyTimes.empty()) return true; if(keyTimes.front() != 0.0 || keyTimes.size() != m_values.size()) keyTimesValid = false; if(m_aattrs->get_calc_mode() != "discrete" && keyTimes.back() != 1.0) keyTimesValid = false; for(size_t i=1;i<keyTimes.size() && keyTimesValid ;i++) keyTimesValid = (keyTimes[i]>keyTimes[i-1]); if(!keyTimesValid) m_logger->trace("<%s id=\"%s\">: invalid key times", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str()); AM_DBG { if(!keyTimes.empty() && keyTimesValid) { std::string str; for(size_t i=0;i<keyTimes.size();i++) {//gcc2.95 Internal compiler err.char sz[32]; char sz[64]; sprintf(sz,"%.3f;", keyTimes[i]);str += sz; } m_logger->debug("%s[%s] keyTimes: %s", m_attrs.get_tag().c_str(), m_attrs.get_id().c_str(), str.c_str()); } } return keyTimesValid;}////////////////////////////////////// underlying_to_animation// A underlying_to_animation is applicable for linear-attributes// linear-attributes define: addition, subtraction and scaling// F: the simple function// T: the type of the attribute// The type T must define addition, subtraction and scalingtemplate <class T>class underlying_to_animation : public animate_node { public: underlying_to_animation(context_type *ctx, const node *n, animate_attrs *aattrs); ~underlying_to_animation(); void prepare_interval(); protected: typedef underlying_to_f<T> F; F m_simple_f; animate_f<F> *m_animate_f; T m_value;};template <class T>underlying_to_animation<T>::underlying_to_animation(context_type *ctx, const node *n, animate_attrs *aattrs): animate_node(ctx, n, aattrs), m_animate_f(0) { std::vector<T> v; m_aattrs->get_values(v); m_value = v[0];}template <class T>underlying_to_animation<T>::~underlying_to_animation() { delete m_animate_f;}template <class T>void underlying_to_animation<T>::prepare_interval() { time_type dur = calc_dur(); time_type sfdur = dur; const time_attrs* ta = get_time_attrs(); if(dur.is_definite() && ta->auto_reverse()) sfdur /= 2; m_simple_f.init(sfdur(), m_value); m_simple_f.set_auto_reverse(ta->auto_reverse()); m_simple_f.set_accelerate(ta->get_accelerate(), ta->get_decelerate()); time_type ad = m_interval.end - m_interval.begin; m_animate_f = new animate_f<F>(m_simple_f, dur(), ad(), m_aattrs->is_accumulative());}////////////////////////////////////// regdim_animation//// A regdim_animation may be used for all region dim animations except for "to" animations// // Animateable region/subregion attributes: "left", "top", "width", "height", "right", "bottom"template <class F>class regdim_animation : public linear_values_animation<F, common::region_dim> { public: regdim_animation(time_node_context *ctx, const node *n, animate_attrs *aattrs) : linear_values_animation<F, common::region_dim>(ctx, n, aattrs) {} void read_dom_value(common::animation_destination *dst, animate_registers& regs) const { regs.rd = dst->get_region_dim(this->m_aattrs->get_target_attr(), true); } bool set_animated_value(common::animation_destination *dst, animate_registers& regs) const { common::region_dim rd = dst->get_region_dim(this->m_aattrs->get_target_attr(), false); if(rd != regs.rd || IGNORE_ATTR_COMP) { AM_DBG { lib::timer::time_type t = this->m_timer->elapsed(); lib::logger::get_logger()->debug("%s(%ld) -> %s", this->m_aattrs->get_target_attr().c_str(), t, ::repr(regs.rd).c_str()); } dst->set_region_dim(this->m_aattrs->get_target_attr(), regs.rd); return true; } return false; } void apply_self_effect(animate_registers& regs) const { if(!this->m_animate_f) return; lib::timer::time_type t = this->m_timer->elapsed(); common::region_dim rd = this->m_animate_f->at(t); if(this->m_aattrs->is_additive()) regs.rd += rd; // add else regs.rd = rd; // override }};class underlying_to_regdim_animation : public underlying_to_animation<common::region_dim> { public: underlying_to_regdim_animation(context_type *ctx, const node *n, animate_attrs *aattrs) : underlying_to_animation<common::region_dim>(ctx, n, aattrs) {} void read_dom_value(common::animation_destination *dst, animate_registers& regs) const { regs.rd = dst->get_region_dim(m_aattrs->get_target_attr(), true); } bool set_animated_value(common::animation_destination *dst, animate_registers& regs) const { common::region_dim rd = dst->get_region_dim(m_aattrs->get_target_attr(), false); if(rd != regs.rd || IGNORE_ATTR_COMP) { AM_DBG { lib::timer::time_type t = m_timer->elapsed(); lib::logger::get_logger()->debug("%s(%ld) -> %s", m_aattrs->get_target_attr().c_str(), t, ::repr(regs.rd).c_str()); } dst->set_region_dim(m_aattrs->get_target_attr(), regs.rd); return true; } return false; } void apply_self_effect(animate_registers& regs) const { if(!m_animate_f) return; lib::timer::time_type t = m_timer->elapsed(); common::region_dim rd = m_animate_f->at(t, regs.rd); regs.rd = rd; // override }};////////////////////////////////////// color_animation//// A color_animation may be used for all backgroundColor/color animations except for "to" animations// // Animateable region/subregion attributes: "backgroundColor", "color"template <class F>class color_animation : public linear_values_animation<F, lib::color_t> { public: color_animation(time_node_context *ctx, const node *n, animate_attrs *aattrs) : linear_values_animation<F, lib::color_t>(ctx, n, aattrs) {} void read_dom_value(common::animation_destination *dst, animate_registers& regs) const { regs.cl = dst->get_region_color(this->m_aattrs->get_target_attr(), true); } bool set_animated_value(common::animation_destination *dst, animate_registers& regs) const { lib::color_t cl = dst->get_region_color(this->m_aattrs->get_target_attr(), false); if(cl != regs.cl || IGNORE_ATTR_COMP) { AM_DBG { lib::timer::time_type t = this->m_timer->elapsed(); lib::logger::get_logger()->debug("%s(%ld) -> 0x%x", this->m_aattrs->get_target_attr().c_str(), t, regs.cl); } dst->set_region_color(this->m_aattrs->get_target_attr(), regs.cl); return true; } return false; } void apply_self_effect(animate_registers& regs) const { if(!this->m_animate_f) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -