pov-out.cpp revision 76addc201c409e81eaaa73fe27cc0f79c4db097c
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * A simple utility for exporting Inkscape svg Shapes as PovRay bezier
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * prisms. Note that this is output-only, and would thus seem to be
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * better placed as an 'export' rather than 'output'. However, Export
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * handles all or partial documents, while this outputs ALL shapes in
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * the current SVG document.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * For information on the PovRay file format, see:
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Authors:
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Bob Jamison <ishmal@inkscape.org>
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Abhishek Sharma
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Copyright (C) 2004-2008 Authors
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Released under GNU GPL, read the file 'COPYING' for more information
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//# M E S S A G E S
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//# U T I L I T Y
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // TODO investigate this. The early return seems that it would abort early.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // Plus is will emit a warning, which may not be proper here.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (SPObject const *obj = item; obj; obj = obj->parent) {
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//# OUTPUT FORMATTING
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * We want to control floating output format
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output data to the buffer, printf()-style
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output a 2d vector
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output a 3d vector
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output a v4d ector
6f3e57ac9d0b054c3169579f3422080b8ba10105mxvoid PovOutput::vec4(double a, double b, double c, double d)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("<%s, %s, %s, %s>", DSTR(a), DSTR(b), DSTR(c), DSTR(d));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output an rgbf color vector
6f3e57ac9d0b054c3169579f3422080b8ba10105mxvoid PovOutput::rgbf(double r, double g, double b, double f)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //"rgbf < %1.3f, %1.3f, %1.3f %1.3f>"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx vec4(r, g, b, f);
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output one bezier's start, start-control, end-control, and end nodes
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //" /*%4d*/ <%f, %f>, <%f, %f>, <%f,%f>, <%f,%f>"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output the file header
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### This PovRay document was generated by Inkscape\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#####################################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### The 'AllShapes' objects at the bottom are provided as a\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### preview of how the output would look in a trace. However,\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### the main intent of this file is to provide the individual\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### For an example of how to use this file, look at\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### If you have any problems with this output, please see the\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### Inkscape project at http://www.inkscape.org, or visit\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("### the #inkscape channel on irc.freenode.net . \n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output the file footer
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output the curve data to buffer
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //### Get the Shape
6f3e57ac9d0b054c3169579f3422080b8ba10105mx if (!SP_IS_SHAPE(item))//Bulia's suggestion. Allow all shapes
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //Try to get the fill color of the shape
6f3e57ac9d0b054c3169579f3422080b8ba10105mx /* fixme: Handle other fill types, even if this means translating gradients to a single
6f3e57ac9d0b054c3169579f3422080b8ba10105mx flat colour. */
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // see color.h for how to parse SPColor
6f3e57ac9d0b054c3169579f3422080b8ba10105mx double const dopacity = ( SP_SCALE24_TO_FLOAT(style->fill_opacity.value)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //gchar *str = g_strdup_printf("rgbf < %1.3f, %1.3f, %1.3f %1.3f>",
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // rgb[0], rgb[1], rgb[2], 1.0 - dopacity);
6f3e57ac9d0b054c3169579f3422080b8ba10105mx povShapes.push_back(shapeInfo); //passed all tests. save the info
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // convert the path to only lineto's and cubic curveto's:
6f3e57ac9d0b054c3169579f3422080b8ba10105mx Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( shape->_curve->get_pathvector() * tf );
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * We need to know the number of segments (NR_CURVETOs/LINETOs, including
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * closing line segment) before we write out segment data. Since we are
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * going to skip degenerate (zero length) paths, we need to loop over all
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * subpaths and segments first.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * For all Subpaths in the <path>
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * For all segments in the subpath, including extra closing segment defined by 2geom
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // Skip zero length segments.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * at moment of writing, 2geom lacks proper initialization of empty intervals in rect...
6f3e57ac9d0b054c3169579f3422080b8ba10105mx Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() );
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * For all Subpaths in the <path>
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * For all segments in the subpath, including extra closing segment defined by 2geom
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx // Skip zero length segments
6f3e57ac9d0b054c3169579f3422080b8ba10105mx p0[X], p0[Y], p0[X], p0[Y], p1[X], p1[Y], p1[X], p1[Y] );
6f3e57ac9d0b054c3169579f3422080b8ba10105mx else if(Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit))
6f3e57ac9d0b054c3169579f3422080b8ba10105mx std::vector<Geom::Point> points = cubic->controlPoints();
6f3e57ac9d0b054c3169579f3422080b8ba10105mx err("logical error, because pathv_to_linear_and_cubic_beziers was used");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return false;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return false;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_MIN_X = %s;\n", id.c_str(), DSTR(cminx));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_CENTER_X = %s;\n", id.c_str(), DSTR((cmaxx+cminx)/2.0));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_MAX_X = %s;\n", id.c_str(), DSTR(cmaxx));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_WIDTH = %s;\n", id.c_str(), DSTR(cmaxx-cminx));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_MIN_Y = %s;\n", id.c_str(), DSTR(cminy));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_CENTER_Y = %s;\n", id.c_str(), DSTR((cmaxy+cminy)/2.0));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_MAX_Y = %s;\n", id.c_str(), DSTR(cmaxy));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_HEIGHT = %s;\n", id.c_str(), DSTR(cmaxy-cminy));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################*/\n\n\n\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Descend the svg tree recursively, translating data
6f3e57ac9d0b054c3169579f3422080b8ba10105mxbool PovOutput::doTreeRecursive(SPDocument *doc, SPObject *obj)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return false;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Descend into children
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (SPObject *child = obj->firstChild() ; child ; child = child->next)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return false;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Output the curve data to buffer
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return false;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //## Let's make a union of all of the Shapes
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*###################################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("###################################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*#### Same union, but with Z-diffs (actually Y in pov) ####*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare AllShapes_Z_Increment = %s;\n", DSTR(zinc));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_Z_Scale = %s_Z_Scale + %s_Z_Increment;\n\n",
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_CENTER_X = %s;\n", pfx, DSTR((maxx+minx)/2.0));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("#declare %s_CENTER_Y = %s;\n", pfx, DSTR((maxy+miny)/2.0));
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("/*##############################################\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx out("##############################################*/\n");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//# M A I N O U T P U T
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Set values back to initial state
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Saves the Shapes of an Inkscape SVG file as PovRay spline definitions
6f3e57ac9d0b054c3169579f3422080b8ba10105mxvoid PovOutput::saveDocument(SPDocument *doc, gchar const *filename_utf8)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //###### SAVE IN POV FORMAT TO BUFFER
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //# Lets do the curves first, to get the stats
6f3e57ac9d0b054c3169579f3422080b8ba10105mx //###### WRITE TO FILE
6f3e57ac9d0b054c3169579f3422080b8ba10105mx FILE *f = Inkscape::IO::fopen_utf8name(filename_utf8, "w");
6f3e57ac9d0b054c3169579f3422080b8ba10105mx for (String::iterator iter = outbuf.begin() ; iter!=outbuf.end(); ++iter)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//# EXTENSION API
6f3e57ac9d0b054c3169579f3422080b8ba10105mx//########################################################################
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * API call to save document
6f3e57ac9d0b054c3169579f3422080b8ba10105mx /* See comments in JavaFSOutput::save re the name `filename_utf8'. */
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * Make sure that we are in the database
6f3e57ac9d0b054c3169579f3422080b8ba10105mxbool PovOutput::check (Inkscape::Extension::Extension */*module*/)
6f3e57ac9d0b054c3169579f3422080b8ba10105mx /* We don't need a Key
6f3e57ac9d0b054c3169579f3422080b8ba10105mx if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_POV))
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return FALSE;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx return true;
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * This is the definition of PovRay output. This function just
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * calls the extension system with the memory allocated XML that
6f3e57ac9d0b054c3169579f3422080b8ba10105mx * describes the data.
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<id>org.inkscape.output.pov</id>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<output>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<extension>.pov</extension>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<mimetype>text/x-povray-script</mimetype>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<filetypename>" N_("PovRay (*.pov) (paths and shapes only)") "</filetypename>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "<filetypetooltip>" N_("PovRay Raytracer File") "</filetypetooltip>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "</output>\n"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx "</inkscape-extension>",
6f3e57ac9d0b054c3169579f3422080b8ba10105mx} // namespace Internal
6f3e57ac9d0b054c3169579f3422080b8ba10105mx} // namespace Extension
6f3e57ac9d0b054c3169579f3422080b8ba10105mx} // namespace Inkscape
6f3e57ac9d0b054c3169579f3422080b8ba10105mx Local Variables:
6f3e57ac9d0b054c3169579f3422080b8ba10105mx c-file-style:"stroustrup"
6f3e57ac9d0b054c3169579f3422080b8ba10105mx c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
6f3e57ac9d0b054c3169579f3422080b8ba10105mx indent-tabs-mode:nil
6f3e57ac9d0b054c3169579f3422080b8ba10105mx fill-column:99
6f3e57ac9d0b054c3169579f3422080b8ba10105mx// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :