X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftrunk%2Fsrc%2Fsynfig%2Fsavecanvas.cpp;h=a2ae0d92e2594c258b83d03e57148385796632ca;hb=9459638ad6797b8139f1e9f0715c96076dbf0890;hp=3fbed5f0655b031471e5440f1594e3231f0a31d2;hpb=cc54c38609ee9745ad678e5e9b9d7d2912be9c95;p=synfig.git diff --git a/synfig-core/trunk/src/synfig/savecanvas.cpp b/synfig-core/trunk/src/synfig/savecanvas.cpp index 3fbed5f..a2ae0d9 100644 --- a/synfig-core/trunk/src/synfig/savecanvas.cpp +++ b/synfig-core/trunk/src/synfig/savecanvas.cpp @@ -6,6 +6,7 @@ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** Copyright (c) 2007, 2008 Chris Moore ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as @@ -57,6 +58,10 @@ #include "gradient.h" #include +extern "C" { +#include +} + #endif /* === U S I N G =========================================================== */ @@ -74,6 +79,9 @@ using namespace synfig; /* === G L O B A L S ======================================================= */ +ReleaseVersion save_canvas_version = ReleaseVersion(RELEASE_VERSION_END-1); +int valuenode_too_new_count; + /* === P R O C E D U R E S ================================================= */ xmlpp::Element* encode_canvas(xmlpp::Element* root,Canvas::ConstHandle canvas); @@ -96,7 +104,7 @@ xmlpp::Element* encode_real(xmlpp::Element* root,Real v) return root; } -xmlpp::Element* encode_time(xmlpp::Element* root,Time t, float fps=0) +xmlpp::Element* encode_time(xmlpp::Element* root,Time t, float /*fps*/=0) { root->set_name("time"); //root->set_attribute("value",t.get_string(fps)); @@ -243,7 +251,7 @@ xmlpp::Element* encode_value(xmlpp::Element* root,const ValueBase &data,Canvas:: root->set_name("nil"); return root; default: - synfig::error(strprintf("Unknown value(%s), cannot create XML representation!",ValueBase::type_name(data.get_type()).c_str())); + synfig::error(strprintf(_("Unknown value(%s), cannot create XML representation!"),ValueBase::type_local_name(data.get_type()).c_str())); root->set_name("nil"); return root; } @@ -268,8 +276,18 @@ xmlpp::Element* encode_animated(xmlpp::Element* root,ValueNode_Animated::ConstHa //waypoint_node->add_child(encode_value(iter->get_value(),canvas)); if(iter->get_value_node()->is_exported()) waypoint_node->set_attribute("use",iter->get_value_node()->get_relative_id(canvas)); - else - encode_value_node(waypoint_node->add_child("value_node"),iter->get_value_node(),canvas); + else { + ValueNode::ConstHandle value_node = iter->get_value_node(); + if(ValueNode_Const::ConstHandle::cast_dynamic(value_node)) { + const ValueBase data = ValueNode_Const::ConstHandle::cast_dynamic(value_node)->get_value(); + if (data.get_type() == ValueBase::TYPE_CANVAS) + waypoint_node->set_attribute("use",data.get(Canvas::Handle()).get()->get_relative_id(canvas)); + else + encode_value_node(waypoint_node->add_child("value_node"),iter->get_value_node(),canvas); + } + else + encode_value_node(waypoint_node->add_child("value_node"),iter->get_value_node(),canvas); + } switch(iter->get_before()) { @@ -286,7 +304,7 @@ xmlpp::Element* encode_animated(xmlpp::Element* root,ValueNode_Animated::ConstHa waypoint_node->set_attribute("before","constant"); break; case INTERPOLATION_TCB: - // This is the default value, so don't add a new attribute + waypoint_node->set_attribute("before","auto"); break; default: error("Unknown waypoint type for \"before\" attribute"); @@ -307,16 +325,16 @@ xmlpp::Element* encode_animated(xmlpp::Element* root,ValueNode_Animated::ConstHa waypoint_node->set_attribute("after","constant"); break; case INTERPOLATION_TCB: - // This is the default value, so don't add a new attribute + waypoint_node->set_attribute("after","auto"); break; default: - error("Unknown waypoint type for \"before\" attribute"); + error("Unknown waypoint type for \"after\" attribute"); } if(iter->get_tension()!=0.0) waypoint_node->set_attribute("tension",strprintf("%f",iter->get_tension())); - if(iter->get_time_tension()!=0.0) - waypoint_node->set_attribute("temporal-tension",strprintf("%f",iter->get_time_tension())); + if(iter->get_temporal_tension()!=0.0) + waypoint_node->set_attribute("temporal-tension",strprintf("%f",iter->get_temporal_tension())); if(iter->get_continuity()!=0.0) waypoint_node->set_attribute("continuity",strprintf("%f",iter->get_continuity())); if(iter->get_bias()!=0.0) @@ -327,27 +345,6 @@ xmlpp::Element* encode_animated(xmlpp::Element* root,ValueNode_Animated::ConstHa return root; } -xmlpp::Element* encode_composite(xmlpp::Element* root,ValueNode_Composite::ConstHandle value_node,Canvas::ConstHandle canvas=0) -{ - assert(value_node); - root->set_name("composite"); - - root->set_attribute("type",ValueBase::type_name(value_node->get_type())); - - int i; - for(i=0;ilink_count();i++) - { - string name(strprintf("c%d",i+1)); - assert(value_node->get_link(i)); - if(value_node->get_link(i)->is_exported()) - root->set_attribute(name,value_node->get_link(i)->get_relative_id(canvas)); - else - encode_value_node(root->add_child(name)->add_child("value_node"),value_node->get_link(i).constant(),canvas); - } - - return root; -} - xmlpp::Element* encode_subtract(xmlpp::Element* root,ValueNode_Subtract::ConstHandle value_node,Canvas::ConstHandle canvas=0) { assert(value_node); @@ -470,7 +467,26 @@ xmlpp::Element* encode_dynamic_list(xmlpp::Element* root,ValueNode_DynamicList:: xmlpp::Element* encode_linkable_value_node(xmlpp::Element* root,LinkableValueNode::ConstHandle value_node,Canvas::ConstHandle canvas=0) { assert(value_node); - root->set_name(value_node->get_name()); + + String name(value_node->get_name()); + ReleaseVersion saving_version(get_file_version()); + ReleaseVersion feature_version(LinkableValueNode::book()[name].release_version); + + if (saving_version < feature_version) + { + valuenode_too_new_count++; + warning("can't save <%s> valuenodes in this old file format version", name.c_str()); + + ValueBase value((*value_node)(0)); + encode_value(root,value,canvas); + + // ValueNode_Const::ConstHandle const_value(ValueNode_Const::create((*value_node)(0))); + // encode_value_node(root,const_value,canvas); + + return root; + } + + root->set_name(name); root->set_attribute("type",ValueBase::type_name(value_node->get_type())); @@ -496,9 +512,6 @@ xmlpp::Element* encode_value_node(xmlpp::Element* root,ValueNode::ConstHandle va if(ValueNode_Animated::ConstHandle::cast_dynamic(value_node)) encode_animated(root,ValueNode_Animated::ConstHandle::cast_dynamic(value_node),canvas); else - if(ValueNode_Composite::ConstHandle::cast_dynamic(value_node)) - encode_composite(root,ValueNode_Composite::ConstHandle::cast_dynamic(value_node),canvas); - else if(ValueNode_Subtract::ConstHandle::cast_dynamic(value_node)) encode_subtract(root,ValueNode_Subtract::ConstHandle::cast_dynamic(value_node),canvas); else @@ -557,7 +570,7 @@ xmlpp::Element* encode_layer(xmlpp::Element* root,Layer::ConstHandle layer) handle value_node=dynamic_param_list.find(iter->get_name())->second; - // If the valuenode.has no ID, then it must be defined in-place + // If the valuenode has no ID, then it must be defined in-place if(value_node->get_id().empty()) { encode_value_node(node->add_child("value_node"),value_node,layer->get_canvas().constant()); @@ -573,20 +586,29 @@ xmlpp::Element* encode_layer(xmlpp::Element* root,Layer::ConstHandle layer) ValueBase value=layer->get_param(iter->get_name()); if(!value.is_valid()) { - error("Layer doesn't know it's own vocabulary -- "+iter->get_name()); + error("Layer doesn't know its own vocabulary -- "+iter->get_name()); continue; } - if(value.get_type()==ValueBase::TYPE_CANVAS && !value.get(Canvas::LooseHandle())->is_inline()) + if(value.get_type()==ValueBase::TYPE_CANVAS) { - Canvas::Handle child(value.get(Canvas::LooseHandle())); + // the ->is_inline() below was crashing if the canvas + // contained a PasteCanvas with the default Canvas setting; this avoids the crash + if (!value.get(Canvas::LooseHandle())) + continue; - if(!value.get(Canvas::Handle())) + if (!value.get(Canvas::LooseHandle())->is_inline()) + { + Canvas::Handle child(value.get(Canvas::LooseHandle())); + + if(!value.get(Canvas::Handle())) + continue; + xmlpp::Element *node=root->add_child("param"); + node->set_attribute("name",iter->get_name()); + node->set_attribute("use",child->get_relative_id(layer->get_canvas())); continue; - xmlpp::Element *node=root->add_child("param"); - node->set_attribute("name",iter->get_name()); - node->set_attribute("use",child->get_relative_id(layer->get_canvas())); - continue; + } } xmlpp::Element *node=root->add_child("param"); node->set_attribute("name",iter->get_name()); @@ -606,7 +628,7 @@ xmlpp::Element* encode_canvas(xmlpp::Element* root,Canvas::ConstHandle canvas) root->set_name("canvas"); if(canvas->is_root()) - root->set_attribute("version","0.1"); + root->set_attribute("version",canvas->get_version()); if(!canvas->get_id().empty() && !canvas->is_root() && !canvas->is_inline()) root->set_attribute("id",canvas->get_id()); @@ -675,7 +697,8 @@ xmlpp::Element* encode_canvas(xmlpp::Element* root,Canvas::ConstHandle canvas) } // Output the section - if(!canvas->is_inline() && !canvas->value_node_list().empty() || !canvas->children().empty()) + //! \todo check where the parentheses should really go - around the && or the ||? + if((!canvas->is_inline() && !canvas->value_node_list().empty()) || !canvas->children().empty()) { xmlpp::Element *node=root->add_child("defs"); const ValueNodeList &value_node_list(canvas->value_node_list()); @@ -707,6 +730,18 @@ xmlpp::Element* encode_canvas(xmlpp::Element* root,Canvas::ConstHandle canvas) return root; } +xmlpp::Element* encode_canvas_toplevel(xmlpp::Element* root,Canvas::ConstHandle canvas) +{ + valuenode_too_new_count = 0; + + xmlpp::Element* ret = encode_canvas(root, canvas); + + if (valuenode_too_new_count) + warning("saved %d valuenodes as constant values in old file format\n", valuenode_too_new_count); + + return ret; +} + bool synfig::save_canvas(const String &filename, Canvas::ConstHandle canvas) { @@ -714,37 +749,41 @@ synfig::save_canvas(const String &filename, Canvas::ConstHandle canvas) synfig::String tmp_filename(filename+".TMP"); + if (filename_extension(filename) == ".sifz") + xmlSetCompressMode(9); + else + xmlSetCompressMode(0); + try { assert(canvas); xmlpp::Document document; - encode_canvas(document.create_root_node("canvas"),canvas); + encode_canvas_toplevel(document.create_root_node("canvas"),canvas); document.write_to_file_formatted(tmp_filename); - } - catch(...) { synfig::error("synfig::save_canvas(): Caught unknown exception"); return false; } - #ifdef _WIN32 - // On Win32 platforms, rename() has bad behavior. work around it. - char old_file[80]="sif.XXXXXXXX"; - mktemp(old_file); - rename(filename.c_str(),old_file); - if(rename(tmp_filename.c_str(),filename.c_str())!=0) - { - rename(old_file,tmp_filename.c_str()); - synfig::error("synfig::save_canvas(): Unable to rename file to correct filename, errno=%d",errno); - return false; - } - remove(old_file); + // On Win32 platforms, rename() has bad behavior. work around it. + char old_file[80]="sif.XXXXXXXX"; + mktemp(old_file); + rename(filename.c_str(),old_file); + if(rename(tmp_filename.c_str(),filename.c_str())!=0) + { + rename(old_file,tmp_filename.c_str()); + synfig::error("synfig::save_canvas(): Unable to rename file to correct filename, errno=%d",errno); + return false; + } + remove(old_file); #else - if(rename(tmp_filename.c_str(),filename.c_str())!=0) - { - synfig::error("synfig::save_canvas(): Unable to rename file to correct filename, errno=%d",errno); - return false; - } + if(rename(tmp_filename.c_str(),filename.c_str())!=0) + { + synfig::error("synfig::save_canvas(): Unable to rename file to correct filename, errno=%d",errno); + return false; + } #endif + } + catch(...) { synfig::error("synfig::save_canvas(): Caught unknown exception"); return false; } return true; } @@ -757,7 +796,19 @@ synfig::canvas_to_string(Canvas::ConstHandle canvas) xmlpp::Document document; - encode_canvas(document.create_root_node("canvas"),canvas); + encode_canvas_toplevel(document.create_root_node("canvas"),canvas); return document.write_to_string_formatted(); } + +void +synfig::set_file_version(ReleaseVersion version) +{ + save_canvas_version = version; +} + +ReleaseVersion +synfig::get_file_version() +{ + return save_canvas_version; +}