/* libsswf_tag_export.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */

/*

Copyright (c) 2002-2008 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

/** \file
 *
 * \brief The implementation of the sswf::TagExport class
 *
 * This file declares the body of the functions which are not
 * inline. It is part of the SSWF library.
 */

#include	"sswf/libsswf.h"

using namespace sswf;



/////////////////////////////////////////// TagExport


/** \class sswf::TagExport
 *
 * \brief The object used to export objects to another movie
 *
 * The export tag is used to share objects defined in this
 * movie to the outside world. Other SWF movies can reference
 * this movie and the exported objects with the use of an
 * sswf::TagImport tag.
 *
 * \sa sswf::TagImport
 * \sa <a href="../SWFalexref.html#tag_export">SWF Alexis' Reference&mdash;Export</a>
 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
 */


/** \brief Initialize the tag export
 *
 * The constructor initialize the tag export with an empty list
 * of objects. The objects can later be added with a call to
 * the sswf::TagExport::SetOption(sswf_id_t id, const char *name)
 * function.
 *
 * \sa sswf::TagExport::SetOption(sswf_id_t id, const char *name)
 */
TagExport::TagExport(TagBase *parent)
	: TagBase("export", parent)
{
	//f_objects = ...
}


/** \brief Get the flags representing this tag
 *
 * A TagExport is similar to a definition (DEFINE) event thought
 * it does not really define much for this very movie.
 *
 * Only one sswf::TagExport can be created in an entire movie (UNIQUE).
 * I did not test, but it is likely that only the first or last
 * sswf::TagExport has an effect. It is also possible that all
 * sswf::TagExport tags are cumulative.
 *
 * This tag includes one or more references.
 */
TagBase::swf_type_t TagExport::TypeFlags(void) const
{
	return SWF_TYPE_DEFINE | SWF_TYPE_UNIQUE | SWF_TYPE_REFERENCE;
}


/** \brief Adds one object reference to the TagExport
 *
 * This function is used to add one object reference and a name
 * to the export tag. 
 *
 * The name is what the object will be found as from the external
 * world. The reference id is the id of the object being exported.
 * Note that exporting objects themselves referencing other objects
 * such as a sprite is legal and implies that all the objects
 * within that sprite are also exported. However, if these
 * objects are not mentioned in the sswf::TagExport list of exported
 * objects, they cannot be directly accessed.
 *
 * The order in which objects are added does not matter. The TagExport
 * itself, however, needs to appear after the objects being exported.
 *
 * \note
 * The object being referenced must be a definition tag (i.e. its
 * sswf::TagBase::TypeFlags() must return the
 * sswf::TagBase::SWF_TYPE_DEFINE bit set).
 *
 * \param id		The identifier of the object being exported.
 * \param name		This is the name used to find the object from an
 *			sswf::TagImport tag (i.e. the names must match.)
 * \param used_glyphs	A list of glyphs to include in a font; if not
 *			specified, all the glyphs are added.
 */
void TagExport::SetObject(sswf_id_t id, const char *name, const char *used_glyphs)
{
	export_t	*e;

	e = new export_t;
	MemAttach(e, sizeof(export_t), "TagExport::SetObject() -- object info for export");
	e->f_id = id;
	e->f_name = StrDup(name);
	if(used_glyphs != 0) {
		e->f_used_glyphs = StrDup(used_glyphs);
	}
	else {
		e->f_used_glyphs = 0;
	}

	f_objects.Set(-1, e);
}


/** \brief Test the availability of all the objects
 *
 * This function checks that all the objects referenced with calls
 * to sswf::TagExport::SetObject(sswf_id_t id, const char *name)
 * are indeed available in the SWF animation.
 *
 * Also, it ensures that tags are definitions. This is not a 100%
 * sure test that the given tag can indeed be saved in an export
 * tag, but it will already filter most possible errors.
 *
 * If a font is being exported, then the font is marked as if
 * used by a sswf::TagEditText. The function also ensures that all
 * the glyphs are saved in the font (or at least those you requested
 * when adding the font to the TagExport object.) The fact is that
 * this font could be used by an sswf::TagEditText once imported and
 * there is no way to infer such a thing at this point.
 *
 * Note that the use of an sswf::TagExport object forces a
 * minimum version of 5.
 *
 * \sa sswf::TagExport::SetObject(sswf_id_t id, const char *name)
 * \sa sswf::TagEditText
 */
ErrorManager::error_code_t TagExport::PreSave(void)
{
	TagBase		*t;
	long		idx, max;
	export_t	*e;

	MinimumVersion(5);

	max = f_objects.Count();
	for(idx = 0; idx < max; idx++) {
		e = dynamic_cast<export_t *>(f_objects.Get(idx));
		t = FindTagWithID(e->f_id, false);
		if(t == 0) {
			return OnError(ErrorManager::ERROR_CODE_UNKNOWN_OBJECT_EXPORTED, "TagExport cannot find object \"%s\" with ID #%d.", e->f_name, e->f_id);
		}
		if((t->TypeFlags() & SWF_TYPE_DEFINE) == 0) {
			return OnError(ErrorManager::ERROR_CODE_UNKNOWN_OBJECT_EXPORTED, "TagExport cannot export object \"%s\" with ID #%d: it is not a definition tag.", e->f_name, e->f_id);
		}
		// if we have a font we want to force it to save all the glyphs
		if(strcmp(t->Name(), "font") == 0) {
			// Mark that all the glyphs (or the user defined glyphs) are to be saved
			dynamic_cast<TagFont *>(t)->SetUsedGlyphs(e->f_used_glyphs, true);

			// since we cannot know whether the font will be used in a TagEditText
			// we automatically mark it so this way it can be used by such a tag.
			dynamic_cast<TagFont *>(t)->SetUsedByEditText();
		}
	}

	return ErrorManager::ERROR_CODE_NONE;
}


/** \brief Save the export tag in the specified Data buffer
 *
 * This function saves the sswf::TagExport object in the
 * specified sswf::Data object.
 *
 * This tag is composed of a counter followed by an array
 * of identifiers and names.
 */
ErrorManager::error_code_t TagExport::Save(Data& data)
{
	Data				sub_data;
	long				idx, max;
	export_t			*e;
	ErrorManager::error_code_t	ec;

	ec = ErrorManager::ERROR_CODE_NONE;

	max = f_objects.Count();
	sub_data.PutShort((unsigned short) max);

	for(idx = 0; idx < max; idx++) {
		e = dynamic_cast<export_t *>(f_objects.Get(idx));
		sub_data.PutShort(e->f_id);
		ec = ErrorManager::KeepFirst(ec, SaveString(sub_data, e->f_name));
	}

	SaveTag(data, SWF_TAG_EXPORT, sub_data.ByteSize());

	data.Append(sub_data);

	return ec;
}





/* The following options fold the documentation; use 'zi' to turn on and off
 *
 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
 */
