+void Tracer::read_data(KeyFrame *keyframe)
+{
+ config.read_data(keyframe);
+}
+
+void Tracer::span_keyframes(KeyFrame *src, int64_t start, int64_t end)
+{
+ TracerConfig src_config;
+ src_config.read_data(src);
+ KeyFrames *keyframes = (KeyFrames *)src->autos;
+ KeyFrame *prev = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
+ TracerConfig prev_config;
+ prev_config.read_data(prev);
+// Always update the first one
+ update_parameter(prev_config, src_config, prev);
+ KeyFrame *curr = (KeyFrame*)prev->next;
+ while( curr && curr->position < end ) {
+ update_parameter(prev_config, src_config, curr);
+ curr = (KeyFrame*)curr->next;
+ }
+}
+
+void TracerPoint::update_parameter(TracerPoint *prev, TracerPoint *src)
+{
+ if( prev->x != src->x ) x = src->x;
+ if( prev->y != src->y ) y = src->y;
+}
+
+void Tracer::update_parameter(TracerConfig &prev_config, TracerConfig &src_config,
+ KeyFrame *keyframe)
+{
+ TracerConfig dst_config;
+ dst_config.read_data(keyframe);
+ if( prev_config.draw != src_config.draw )
+ dst_config.draw = src_config.draw;
+ if( prev_config.fill != src_config.fill )
+ dst_config.fill = src_config.fill;
+ if( prev_config.feather != src_config.feather )
+ dst_config.feather = src_config.feather;
+ if( prev_config.invert != src_config.invert )
+ dst_config.invert = src_config.invert;
+ if( prev_config.radius != src_config.radius )
+ dst_config.radius = src_config.radius;
+ int src_points = src_config.points.size();
+ int dst_points = dst_config.points.size();
+ int prev_points = prev_config.points.size();
+ int npoints = bmin(prev_points, bmin(src_points, dst_points));
+ for( int i=0; i<npoints; ++i ) {
+ TracerPoint *prev_point = prev_config.points[i];
+ TracerPoint *src_point = src_config.points[i];
+ TracerPoint *dst_point = dst_config.points[i];
+ dst_point->update_parameter(prev_point, src_point);
+ }
+ dst_config.save_data(keyframe);
+}