X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fextension%2Finternal%2Fpov-out.cpp;h=6b8a5ce070744cb441d3da50119fc146cd632710;hb=025db6f90298127a666cd24bcfc2e22fd35ca84d;hp=05811604038f727e39f842ed5eb65e044b463e0e;hpb=a6988c83e9af8585b15319bf204be9382260b739;p=inkscape.git diff --git a/src/extension/internal/pov-out.cpp b/src/extension/internal/pov-out.cpp index 058116040..6b8a5ce07 100644 --- a/src/extension/internal/pov-out.cpp +++ b/src/extension/internal/pov-out.cpp @@ -9,9 +9,9 @@ * http://www.povray.org * * Authors: - * Bob Jamison + * Bob Jamison * - * Copyright (C) 2004 Authors + * Copyright (C) 2004-2008 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -21,179 +21,266 @@ # include #endif #include "pov-out.h" -#include "inkscape.h" -#include "sp-path.h" +#include +#include +#include #include -#include "display/curve.h" -#include "libnr/n-art-bpath.h" -#include "extension/system.h" +#include +#include +#include <2geom/pathvector.h> +#include <2geom/rect.h> +#include <2geom/bezier-curve.h> +#include <2geom/hvlinesegment.h> +#include "helper/geom.h" +#include "helper/geom-curves.h" +#include + +#include +#include +#include + + +namespace Inkscape +{ +namespace Extension +{ +namespace Internal +{ +//######################################################################## +//# M E S S A G E S +//######################################################################## -#include "io/sys.h" +static void err(const char *fmt, ...) +{ + va_list args; + g_log(NULL, G_LOG_LEVEL_WARNING, "Pov-out err: "); + va_start(args, fmt); + g_logv(NULL, G_LOG_LEVEL_WARNING, fmt, args); + va_end(args); + g_log(NULL, G_LOG_LEVEL_WARNING, "\n"); +} -namespace Inkscape { -namespace Extension { -namespace Internal { -static const char * -dstr(gchar *sbuffer, double d) -{ - return (const char *)g_ascii_formatd(sbuffer, - G_ASCII_DTOSTR_BUF_SIZE, "%.8g", (gdouble)d); +//######################################################################## +//# U T I L I T Y +//######################################################################## + + +static double +effective_opacity(SPItem const *item) +{ + double ret = 1.0; + for (SPObject const *obj = item; obj; obj = obj->parent) + { + SPStyle const *const style = SP_OBJECT_STYLE(obj); + g_return_val_if_fail(style, ret); + ret *= SP_SCALE24_TO_FLOAT(style->opacity.value); + } + return ret; } + + + +//######################################################################## +//# OUTPUT FORMATTING +//######################################################################## + + /** - * Make sure that we are in the database + * We want to control floating output format */ -bool -PovOutput::check (Inkscape::Extension::Extension *module) +static PovOutput::String dstr(double d) { - /* We don't need a Key - if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_POV)) - return FALSE; - */ + char dbuf[G_ASCII_DTOSTR_BUF_SIZE+1]; + g_ascii_formatd(dbuf, G_ASCII_DTOSTR_BUF_SIZE, + "%.8f", (gdouble)d); + PovOutput::String s = dbuf; + return s; +} - return TRUE; +#define DSTR(d) (dstr(d).c_str()) + + +/** + * Output data to the buffer, printf()-style + */ +void PovOutput::out(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + gchar *output = g_strdup_vprintf(fmt, args); + va_end(args); + outbuf.append(output); + g_free(output); } + /** - * This function searches the Repr tree recursively from the given node, - * and adds refs to all nodes with the given name, to the result vector + * Output a 2d vector */ -static void -findElementsByTagName(std::vector &results, - Inkscape::XML::Node *node, - char const *name) +void PovOutput::vec2(double a, double b) { - if ( !name - || strcmp(node->name(), name) == 0 ) { - results.push_back(node); - } + out("<%s, %s>", DSTR(a), DSTR(b)); +} + - for (Inkscape::XML::Node *child = node->firstChild() ; child ; child = child->next()) - findElementsByTagName( results, child, name ); +/** + * Output a 3d vector + */ +void PovOutput::vec3(double a, double b, double c) +{ + out("<%s, %s, %s>", DSTR(a), DSTR(b), DSTR(c)); } + /** - * used for saving information about shapes + * Output a v4d ector */ -class PovShapeInfo +void PovOutput::vec4(double a, double b, double c, double d) { -public: - PovShapeInfo() - {} - virtual ~PovShapeInfo() - {} - std::string id; - std::string color; -}; + out("<%s, %s, %s, %s>", DSTR(a), DSTR(b), DSTR(c), DSTR(d)); +} -static double -effective_opacity(SPItem const *item) +/** + * Output an rgbf color vector + */ +void PovOutput::rgbf(double r, double g, double b, double f) { - double ret = 1.0; - for (SPObject const *obj = item; obj; obj = obj->parent) { - SPStyle const *const style = SP_OBJECT_STYLE(obj); - g_return_val_if_fail(style, ret); - ret *= SP_SCALE24_TO_FLOAT(style->opacity.value); - } - return ret; + //"rgbf < %1.3f, %1.3f, %1.3f %1.3f>" + out("rgbf "); + vec4(r, g, b, f); } + /** - * Saves the of an Inkscape SVG file as PovRay spline definitions -*/ -void -PovOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *uri) + * Output one bezier's start, start-control, end-control, and end nodes + */ +void PovOutput::segment(int segNr, + double startX, double startY, + double startCtrlX, double startCtrlY, + double endCtrlX, double endCtrlY, + double endX, double endY) { - std::vectorresults; - //findElementsByTagName(results, SP_ACTIVE_DOCUMENT->rroot, "path"); - findElementsByTagName(results, SP_ACTIVE_DOCUMENT->rroot, NULL);//Check all nodes - if (results.size() == 0) - return; - Inkscape::IO::dump_fopen_call(uri, "L"); - FILE *f = Inkscape::IO::fopen_utf8name(uri, "w"); - if (!f) - return; + //" /*%4d*/ <%f, %f>, <%f, %f>, <%f,%f>, <%f,%f>" + out(" /*%4d*/ ", segNr); + vec2(startX, startY); + out(", "); + vec2(startCtrlX, startCtrlY); + out(", "); + vec2(endCtrlX, endCtrlY); + out(", "); + vec2(endX, endY); +} + + + + +/** + * Output the file header + */ +bool PovOutput::doHeader() +{ time_t tim = time(NULL); - fprintf(f, "/*#################################################\n"); - fprintf(f, "### This PovRay document was generated by Inkscape\n"); - fprintf(f, "### http://www.inkscape.org\n"); - fprintf(f, "### Created: %s", ctime(&tim)); - fprintf(f, "##################################################*/\n\n\n"); - - std::vectorpovShapes; //A list for saving information about the shapes - - //we only need 8 for printf() calls that call dstr() 8 times - gchar s1[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s2[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s3[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s4[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s5[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s6[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s7[G_ASCII_DTOSTR_BUF_SIZE + 1]; - gchar s8[G_ASCII_DTOSTR_BUF_SIZE + 1]; - - double bignum = 1000000.0; - double minx = bignum; - double maxx = -bignum; - double miny = bignum; - double maxy = -bignum; - - - - unsigned indx; - for (indx = 0; indx < results.size() ; indx++) - { - //### Fetch the object from the repr info - Inkscape::XML::Node *rpath = results[indx]; - gchar *id = (gchar *)rpath->attribute("id"); - SPObject *reprobj = SP_ACTIVE_DOCUMENT->getObjectByRepr(rpath); - if (!reprobj) - continue; - - //### Get the transform of the item - if (!SP_IS_ITEM(reprobj)) - { - continue; - } - SPItem *item = SP_ITEM(reprobj); - NR::Matrix tf = sp_item_i2d_affine(item); + out("/*###################################################################\n"); + out("### This PovRay document was generated by Inkscape\n"); + out("### http://www.inkscape.org\n"); + out("### Created: %s", ctime(&tim)); + out("### Version: %s\n", INKSCAPE_VERSION); + out("#####################################################################\n"); + out("### NOTES:\n"); + out("### ============\n"); + out("### POVRay information can be found at\n"); + out("### http://www.povray.org\n"); + out("###\n"); + out("### The 'AllShapes' objects at the bottom are provided as a\n"); + out("### preview of how the output would look in a trace. However,\n"); + out("### the main intent of this file is to provide the individual\n"); + out("### shapes for inclusion in a POV project.\n"); + out("###\n"); + out("### For an example of how to use this file, look at\n"); + out("### share/examples/istest.pov\n"); + out("###\n"); + out("### If you have any problems with this output, please see the\n"); + out("### Inkscape project at http://www.inkscape.org, or visit\n"); + out("### the #inkscape channel on irc.freenode.net . \n"); + out("###\n"); + out("###################################################################*/\n"); + out("\n\n"); + out("/*###################################################################\n"); + out("## Exports in this file\n"); + out("##==========================\n"); + out("## Shapes : %d\n", nrShapes); + out("## Segments : %d\n", nrSegments); + out("## Nodes : %d\n", nrNodes); + out("###################################################################*/\n"); + out("\n\n\n"); + return true; +} - //### Get the Shape - if (!SP_IS_SHAPE(reprobj))//Bulia's suggestion. Allow all shapes - { - continue; - } - SPShape *shape = SP_SHAPE(reprobj); - SPCurve *curve = shape->curve; - if (sp_curve_empty(curve)) - continue; - PovShapeInfo shapeInfo; - shapeInfo.id = id; - shapeInfo.color = ""; +/** + * Output the file footer + */ +bool PovOutput::doTail() +{ + out("\n\n"); + out("/*###################################################################\n"); + out("### E N D F I L E\n"); + out("###################################################################*/\n"); + out("\n\n"); + return true; +} + + + +/** + * Output the curve data to buffer + */ +bool PovOutput::doCurve(SPItem *item, const String &id) +{ + using Geom::X; + using Geom::Y; + + //### Get the Shape + if (!SP_IS_SHAPE(item))//Bulia's suggestion. Allow all shapes + return true; + + SPShape *shape = SP_SHAPE(item); + SPCurve *curve = shape->curve; + if (curve->is_empty()) + return true; + + nrShapes++; - //Try to get the fill color of the shape - SPStyle *style = SP_OBJECT_STYLE(shape); - /* fixme: Handle other fill types, even if this means translating gradients to a single + PovShapeInfo shapeInfo; + shapeInfo.id = id; + shapeInfo.color = ""; + + //Try to get the fill color of the shape + SPStyle *style = SP_OBJECT_STYLE(shape); + /* fixme: Handle other fill types, even if this means translating gradients to a single flat colour. */ - if (style && (style->fill.type == SP_PAINT_TYPE_COLOR)) { + if (style) + { + if (style->fill.isColor()) + { // see color.h for how to parse SPColor float rgb[3]; sp_color_get_rgb_floatv(&style->fill.value.color, rgb); @@ -201,246 +288,381 @@ PovOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const * * effective_opacity(shape) ); //gchar *str = g_strdup_printf("rgbf < %1.3f, %1.3f, %1.3f %1.3f>", // rgb[0], rgb[1], rgb[2], 1.0 - dopacity); - gchar *str = g_strdup_printf("rgbf < %s, %s, %s %s>", - dstr(s1, rgb[0]), dstr(s2, rgb[1]), dstr(s3, rgb[2]), dstr(s4, 1.0 - dopacity)); + String rgbf = "rgbf <"; + rgbf.append(dstr(rgb[0])); rgbf.append(", "); + rgbf.append(dstr(rgb[1])); rgbf.append(", "); + rgbf.append(dstr(rgb[2])); rgbf.append(", "); + rgbf.append(dstr(1.0 - dopacity)); rgbf.append(">"); + shapeInfo.color += rgbf; + } + } + + povShapes.push_back(shapeInfo); //passed all tests. save the info + + // convert the path to only lineto's and cubic curveto's: + Geom::Matrix tf = sp_item_i2d_affine(item); + Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf ); - shapeInfo.color += str; - g_free(str); + //Count the NR_CURVETOs/LINETOs (including closing line segment) + int segmentCount = 0; + for(Geom::PathVector::const_iterator it = pathv.begin(); it != pathv.end(); ++it) + { + segmentCount += (*it).size(); + if (it->closed()) + segmentCount += 1; } - povShapes.push_back(shapeInfo); //passed all tests. save the info - - int curveNr; - - //Count the NR_CURVETOs/LINETOs - int segmentCount=0; - NArtBpath *bp = curve->bpath; - for (curveNr=0 ; curveNrlength ; curveNr++, bp++) - if (bp->code == NR_CURVETO || bp->code == NR_LINETO) - segmentCount++; - - bp = curve->bpath; - double cminx = bignum; - double cmaxx = -bignum; - double cminy = bignum; - double cmaxy = -bignum; - double lastx = 0.0; - double lasty = 0.0; - - fprintf(f, "/*##############################################\n"); - fprintf(f, "### PRISM: %s\n", id); - fprintf(f, "##############################################*/\n"); - fprintf(f, "#declare %s = prism {\n", id); - fprintf(f, " linear_sweep\n"); - fprintf(f, " bezier_spline\n"); - fprintf(f, " 1.0, //top\n"); - fprintf(f, " 0.0, //bottom\n"); - fprintf(f, " %d, //nr points\n", segmentCount * 4); - int segmentNr = 0; - for (bp = curve->bpath, curveNr=0 ; curveNrlength ; curveNr++, bp++) { - using NR::X; - using NR::Y; - NR::Point const p1(bp->c(1) * tf); - NR::Point const p2(bp->c(2) * tf); - NR::Point const p3(bp->c(3) * tf); - double const x1 = p1[X], y1 = p1[Y]; - double const x2 = p2[X], y2 = p2[Y]; - double const x3 = p3[X], y3 = p3[Y]; - - switch (bp->code) { - case NR_MOVETO: - case NR_MOVETO_OPEN: - //fprintf(f, "moveto: %f %f\n", bp->x3, bp->y3); - break; - case NR_CURVETO: - - //fprintf(f, " /*%4d*/ <%f, %f>, <%f, %f>, <%f,%f>, <%f,%f>", - // segmentNr++, lastx, lasty, x1, y1, x2, y2, x3, y3); - fprintf(f, " /*%4d*/ <%s, %s>, <%s, %s>, <%s,%s>, <%s,%s>", - segmentNr++, - dstr(s1, lastx), dstr(s2, lasty), - dstr(s3, x1), dstr(s4, y1), - dstr(s5, x2), dstr(s6, y2), - dstr(s7, x3), dstr(s8, y3)); - - if (segmentNr < segmentCount) - fprintf(f, ",\n"); - else - fprintf(f, "\n"); - - if (lastx < cminx) - cminx = lastx; - if (lastx > cmaxx) - cmaxx = lastx; - if (lasty < cminy) - cminy = lasty; - if (lasty > cmaxy) - cmaxy = lasty; - break; - case NR_LINETO: - - //fprintf(f, " /*%4d*/ <%f, %f>, <%f, %f>, <%f,%f>, <%f,%f>", - // segmentNr++, lastx, lasty, lastx, lasty, x3, y3, x3, y3); - fprintf(f, " /*%4d*/ <%s, %s>, <%s, %s>, <%s,%s>, <%s,%s>", - segmentNr++, - dstr(s1, lastx), dstr(s2, lasty), - dstr(s3, lastx), dstr(s4, lasty), - dstr(s5, x3), dstr(s6, y3), - dstr(s7, x3), dstr(s8, y3)); - - if (segmentNr < segmentCount) - fprintf(f, ",\n"); - else - fprintf(f, "\n"); - - //fprintf(f, "lineto\n"); - if (lastx < cminx) - cminx = lastx; - if (lastx > cmaxx) - cmaxx = lastx; - if (lasty < cminy) - cminy = lasty; - if (lasty > cmaxy) - cmaxy = lasty; - break; - case NR_END: - //fprintf(f, "end\n"); - break; + out("/*###################################################\n"); + out("### PRISM: %s\n", id.c_str()); + out("###################################################*/\n"); + out("#declare %s = prism {\n", id.c_str()); + out(" linear_sweep\n"); + out(" bezier_spline\n"); + out(" 1.0, //top\n"); + out(" 0.0, //bottom\n"); + out(" %d //nr points\n", segmentCount * 4); + int segmentNr = 0; + + nrSegments += segmentCount; + + /** + * at moment of writing, 2geom lacks proper initialization of empty intervals in rect... + */ + Geom::Rect cminmax( pathv.front().initialPoint(), pathv.front().initialPoint() ); + + + /** + * For all Subpaths in the + */ + for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) + { + + cminmax.expandTo(pit->initialPoint()); + + /** + * For all segments in the subpath + */ + for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit) + { + + if( is_straight_curve(*cit) ) + { + Geom::Point p0 = cit->initialPoint(); + Geom::Point p1 = cit->finalPoint(); + segment(segmentNr++, + p0[X], p0[Y], p0[X], p0[Y], p1[X], p1[Y], p1[X], p1[Y] ); + nrNodes += 8; + } + else if(Geom::CubicBezier const *cubic = dynamic_cast(&*cit)) + { + std::vector points = cubic->points(); + Geom::Point p0 = points[0]; + Geom::Point p1 = points[1]; + Geom::Point p2 = points[2]; + Geom::Point p3 = points[3]; + segment(segmentNr++, + p0[X],p0[Y], p1[X],p1[Y], p2[X],p2[Y], p3[X],p3[Y]); + nrNodes += 8; + } + else + { + err("logical error, because pathv_to_linear_and_cubic_beziers was used"); + return false; + } + + if (segmentNr < segmentCount) + out(",\n"); + else + out("\n"); + + cminmax.expandTo(cit->finalPoint()); + } - lastx = x3; - lasty = y3; } - fprintf(f, "}\n"); - /* - fprintf(f, "#declare %s_MIN_X = %4.3f;\n", id, cminx); - fprintf(f, "#declare %s_CENTER_X = %4.3f;\n", id, (cmaxx+cminx)/2.0); - fprintf(f, "#declare %s_MAX_X = %4.3f;\n", id, cmaxx); - fprintf(f, "#declare %s_WIDTH = %4.3f;\n", id, cmaxx-cminx); - fprintf(f, "#declare %s_MIN_Y = %4.3f;\n", id, cminy); - fprintf(f, "#declare %s_CENTER_Y = %4.3f;\n", id, (cmaxy+cminy)/2.0); - fprintf(f, "#declare %s_MAX_Y = %4.3f;\n", id, cmaxy); - fprintf(f, "#declare %s_HEIGHT = %4.3f;\n", id, cmaxy-cminy); - */ - fprintf(f, "#declare %s_MIN_X = %s;\n", id, dstr(s1, cminx)); - fprintf(f, "#declare %s_CENTER_X = %s;\n", id, dstr(s1, (cmaxx+cminx)/2.0)); - fprintf(f, "#declare %s_MAX_X = %s;\n", id, dstr(s1, cmaxx)); - fprintf(f, "#declare %s_WIDTH = %s;\n", id, dstr(s1, cmaxx-cminx)); - fprintf(f, "#declare %s_MIN_Y = %s;\n", id, dstr(s1, cminy)); - fprintf(f, "#declare %s_CENTER_Y = %s;\n", id, dstr(s1, (cmaxy+cminy)/2.0)); - fprintf(f, "#declare %s_MAX_Y = %s;\n", id, dstr(s1, cmaxy)); - fprintf(f, "#declare %s_HEIGHT = %s;\n", id, dstr(s1, cmaxy-cminy)); - if (shapeInfo.color.length()>0) - fprintf(f, "#declare %s_COLOR = %s;\n", - id, shapeInfo.color.c_str()); - fprintf(f, "/*##############################################\n"); - fprintf(f, "### end %s\n", id); - fprintf(f, "##############################################*/\n\n\n\n"); - if (cminx < minx) - minx = cminx; - if (cmaxx > maxx) - maxx = cmaxx; - if (cminy < miny) - miny = cminy; - if (cmaxy > maxy) - maxy = cmaxy; - - - }//for + out("}\n"); + + double cminx = cminmax.min()[X]; + double cmaxx = cminmax.max()[X]; + double cminy = cminmax.min()[Y]; + double cmaxy = cminmax.max()[Y]; + + out("#declare %s_MIN_X = %s;\n", id.c_str(), DSTR(cminx)); + out("#declare %s_CENTER_X = %s;\n", id.c_str(), DSTR((cmaxx+cminx)/2.0)); + out("#declare %s_MAX_X = %s;\n", id.c_str(), DSTR(cmaxx)); + out("#declare %s_WIDTH = %s;\n", id.c_str(), DSTR(cmaxx-cminx)); + out("#declare %s_MIN_Y = %s;\n", id.c_str(), DSTR(cminy)); + out("#declare %s_CENTER_Y = %s;\n", id.c_str(), DSTR((cmaxy+cminy)/2.0)); + out("#declare %s_MAX_Y = %s;\n", id.c_str(), DSTR(cmaxy)); + out("#declare %s_HEIGHT = %s;\n", id.c_str(), DSTR(cmaxy-cminy)); + if (shapeInfo.color.length()>0) + out("#declare %s_COLOR = %s;\n", + id.c_str(), shapeInfo.color.c_str()); + out("/*###################################################\n"); + out("### end %s\n", id.c_str()); + out("###################################################*/\n\n\n\n"); + + if (cminx < minx) + minx = cminx; + if (cmaxx > maxx) + maxx = cmaxx; + if (cminy < miny) + miny = cminy; + if (cmaxy > maxy) + maxy = cmaxy; + + return true; +} +/** + * Descend the svg tree recursively, translating data + */ +bool PovOutput::doTreeRecursive(SPDocument *doc, SPObject *obj) +{ + + String id; + if (!obj->id) + { + char buf[16]; + sprintf(buf, "id%d", idIndex++); + id = buf; + } + else + { + id = obj->id; + } + + if (SP_IS_ITEM(obj)) + { + SPItem *item = SP_ITEM(obj); + if (!doCurve(item, id)) + return false; + } + + /** + * Descend into children + */ + for (SPObject *child = obj->firstChild() ; child ; child = child->next) + { + if (!doTreeRecursive(doc, child)) + return false; + } + + return true; +} + +/** + * Output the curve data to buffer + */ +bool PovOutput::doTree(SPDocument *doc) +{ + double bignum = 1000000.0; + minx = bignum; + maxx = -bignum; + miny = bignum; + maxy = -bignum; + + if (!doTreeRecursive(doc, doc->root)) + return false; //## Let's make a union of all of the Shapes - if (!povShapes.empty()) { - char const *id = "AllShapes"; - fprintf(f, "/*##############################################\n"); - fprintf(f, "### UNION OF ALL SHAPES IN DOCUMENT\n"); - fprintf(f, "##############################################*/\n"); - fprintf(f, "\n\n"); - fprintf(f, "/**\n"); - fprintf(f, " * Allow the user to redefine the finish{}\n"); - fprintf(f, " * by declaring it before #including this file\n"); - fprintf(f, " */\n"); - fprintf(f, "#ifndef (%s_Finish)\n", id); - fprintf(f, "#declare %s_Finish = finish {\n", id); - fprintf(f, " phong 0.5\n"); - fprintf(f, " reflection 0.3\n"); - fprintf(f, " specular 0.5\n"); - fprintf(f, "}\n"); - fprintf(f, "#end\n"); - fprintf(f, "\n\n"); - fprintf(f, "#declare %s = union {\n", id); - for (unsigned i = 0 ; i < povShapes.size() ; i++) { - fprintf(f, " object { %s\n", povShapes[i].id.c_str()); - fprintf(f, " texture { \n"); + if (povShapes.size()>0) + { + String id = "AllShapes"; + char *pfx = (char *)id.c_str(); + out("/*###################################################\n"); + out("### UNION OF ALL SHAPES IN DOCUMENT\n"); + out("###################################################*/\n"); + out("\n\n"); + out("/**\n"); + out(" * Allow the user to redefine the finish{}\n"); + out(" * by declaring it before #including this file\n"); + out(" */\n"); + out("#ifndef (%s_Finish)\n", pfx); + out("#declare %s_Finish = finish {\n", pfx); + out(" phong 0.5\n"); + out(" reflection 0.3\n"); + out(" specular 0.5\n"); + out("}\n"); + out("#end\n"); + out("\n\n"); + out("#declare %s = union {\n", id.c_str()); + for (unsigned i = 0 ; i < povShapes.size() ; i++) + { + out(" object { %s\n", povShapes[i].id.c_str()); + out(" texture { \n"); if (povShapes[i].color.length()>0) - fprintf(f, " pigment { %s }\n", povShapes[i].color.c_str()); + out(" pigment { %s }\n", povShapes[i].color.c_str()); else - fprintf(f, " pigment { rgb <0,0,0> }\n"); - fprintf(f, " finish { %s_Finish }\n", id); - fprintf(f, " } \n"); - fprintf(f, " } \n"); - } - fprintf(f, "}\n\n\n\n"); + out(" pigment { rgb <0,0,0> }\n"); + out(" finish { %s_Finish }\n", pfx); + out(" } \n"); + out(" } \n"); + } + out("}\n\n\n\n"); double zinc = 0.2 / (double)povShapes.size(); - fprintf(f, "/*#### Same union, but with Z-diffs (actually Y in pov) ####*/\n"); - fprintf(f, "\n\n"); - fprintf(f, "/**\n"); - fprintf(f, " * Allow the user to redefine the Z-Increment\n"); - fprintf(f, " */\n"); - fprintf(f, "#ifndef (AllShapes_Z_Increment)\n"); - fprintf(f, "#declare AllShapes_Z_Increment = %s;\n", dstr(s1, zinc)); - fprintf(f, "#end\n"); - fprintf(f, "\n"); - fprintf(f, "#declare AllShapes_Z_Scale = 1.0;\n"); - fprintf(f, "\n\n"); - fprintf(f, "#declare %s_Z = union {\n", id); - for (unsigned i = 0 ; i < povShapes.size() ; i++) { - fprintf(f, " object { %s\n", povShapes[i].id.c_str()); - fprintf(f, " texture { \n"); + out("/*#### Same union, but with Z-diffs (actually Y in pov) ####*/\n"); + out("\n\n"); + out("/**\n"); + out(" * Allow the user to redefine the Z-Increment\n"); + out(" */\n"); + out("#ifndef (AllShapes_Z_Increment)\n"); + out("#declare AllShapes_Z_Increment = %s;\n", DSTR(zinc)); + out("#end\n"); + out("\n"); + out("#declare AllShapes_Z_Scale = 1.0;\n"); + out("\n\n"); + out("#declare %s_Z = union {\n", pfx); + + for (unsigned i = 0 ; i < povShapes.size() ; i++) + { + out(" object { %s\n", povShapes[i].id.c_str()); + out(" texture { \n"); if (povShapes[i].color.length()>0) - fprintf(f, " pigment { %s }\n", povShapes[i].color.c_str()); + out(" pigment { %s }\n", povShapes[i].color.c_str()); else - fprintf(f, " pigment { rgb <0,0,0> }\n"); - fprintf(f, " finish { %s_Finish }\n", id); - fprintf(f, " } \n"); - fprintf(f, " scale <1, %s_Z_Scale, 1>\n", id); - fprintf(f, " } \n"); - fprintf(f, "#declare %s_Z_Scale = %s_Z_Scale + %s_Z_Increment;\n\n", - id, id, id); + out(" pigment { rgb <0,0,0> }\n"); + out(" finish { %s_Finish }\n", pfx); + out(" } \n"); + out(" scale <1, %s_Z_Scale, 1>\n", pfx); + out(" } \n"); + out("#declare %s_Z_Scale = %s_Z_Scale + %s_Z_Increment;\n\n", + pfx, pfx, pfx); + } + + out("}\n"); + + out("#declare %s_MIN_X = %s;\n", pfx, DSTR(minx)); + out("#declare %s_CENTER_X = %s;\n", pfx, DSTR((maxx+minx)/2.0)); + out("#declare %s_MAX_X = %s;\n", pfx, DSTR(maxx)); + out("#declare %s_WIDTH = %s;\n", pfx, DSTR(maxx-minx)); + out("#declare %s_MIN_Y = %s;\n", pfx, DSTR(miny)); + out("#declare %s_CENTER_Y = %s;\n", pfx, DSTR((maxy+miny)/2.0)); + out("#declare %s_MAX_Y = %s;\n", pfx, DSTR(maxy)); + out("#declare %s_HEIGHT = %s;\n", pfx, DSTR(maxy-miny)); + out("/*##############################################\n"); + out("### end %s\n", id.c_str()); + out("##############################################*/\n"); + out("\n\n"); + } + + return true; +} + + +//######################################################################## +//# M A I N O U T P U T +//######################################################################## + + + +/** + * Set values back to initial state + */ +void PovOutput::reset() +{ + nrNodes = 0; + nrSegments = 0; + nrShapes = 0; + idIndex = 0; + outbuf.clear(); + povShapes.clear(); +} + + + +/** + * Saves the Shapes of an Inkscape SVG file as PovRay spline definitions + */ +void PovOutput::saveDocument(SPDocument *doc, gchar const *uri) +{ + reset(); + + //###### SAVE IN POV FORMAT TO BUFFER + //# Lets do the curves first, to get the stats + if (!doTree(doc)) + { + err("Could not output curves for %s", uri); + return; + } + + String curveBuf = outbuf; + outbuf.clear(); + + if (!doHeader()) + { + err("Could not write header for %s", uri); + return; + } + + outbuf.append(curveBuf); + + if (!doTail()) + { + err("Could not write footer for %s", uri); + return; + } + + + + + //###### WRITE TO FILE + Inkscape::IO::dump_fopen_call(uri, "L"); + FILE *f = Inkscape::IO::fopen_utf8name(uri, "w"); + if (!f) + return; + + for (String::iterator iter = outbuf.begin() ; iter!=outbuf.end(); iter++) + { + int ch = *iter; + fputc(ch, f); } - fprintf(f, "}\n"); - /* - fprintf(f, "#declare %s_MIN_X = %4.3f;\n", id, minx); - fprintf(f, "#declare %s_CENTER_X = %4.3f;\n", id, (maxx+minx)/2.0); - fprintf(f, "#declare %s_MAX_X = %4.3f;\n", id, maxx); - fprintf(f, "#declare %s_WIDTH = %4.3f;\n", id, maxx-minx); - fprintf(f, "#declare %s_MIN_Y = %4.3f;\n", id, miny); - fprintf(f, "#declare %s_CENTER_Y = %4.3f;\n", id, (maxy+miny)/2.0); - fprintf(f, "#declare %s_MAX_Y = %4.3f;\n", id, maxy); - fprintf(f, "#declare %s_HEIGHT = %4.3f;\n", id, maxy-miny); - */ - fprintf(f, "#declare %s_MIN_X = %s;\n", id, dstr(s1, minx)); - fprintf(f, "#declare %s_CENTER_X = %s;\n", id, dstr(s1, (maxx+minx)/2.0)); - fprintf(f, "#declare %s_MAX_X = %s;\n", id, dstr(s1, maxx)); - fprintf(f, "#declare %s_WIDTH = %s;\n", id, dstr(s1, maxx-minx)); - fprintf(f, "#declare %s_MIN_Y = %s;\n", id, dstr(s1, miny)); - fprintf(f, "#declare %s_CENTER_Y = %s;\n", id, dstr(s1, (maxy+miny)/2.0)); - fprintf(f, "#declare %s_MAX_Y = %s;\n", id, dstr(s1, maxy)); - fprintf(f, "#declare %s_HEIGHT = %s;\n", id, dstr(s1, maxy-miny)); - fprintf(f, "/*##############################################\n"); - fprintf(f, "### end %s\n", id); - fprintf(f, "##############################################*/\n\n\n\n"); - } - - //All done fclose(f); } + + + +//######################################################################## +//# EXTENSION API +//######################################################################## + + + #include "clear-n_.h" + + +/** + * API call to save document +*/ +void +PovOutput::save(Inkscape::Extension::Output */*mod*/, + SPDocument *doc, gchar const *uri) +{ + saveDocument(doc, uri); +} + + + +/** + * Make sure that we are in the database + */ +bool PovOutput::check (Inkscape::Extension::Extension */*module*/) +{ + /* We don't need a Key + if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_POV)) + return FALSE; + */ + + return true; +} + + + /** * This is the definition of PovRay output. This function just * calls the extension system with the memory allocated XML that @@ -450,7 +672,7 @@ void PovOutput::init() { Inkscape::Extension::build_from_mem( - "\n" + "\n" "" N_("PovRay Output") "\n" "org.inkscape.output.pov\n" "\n" @@ -467,9 +689,9 @@ PovOutput::init() -} //namespace Internal -} //namespace Extension -} //namespace Inkscape +} // namespace Internal +} // namespace Extension +} // namespace Inkscape /*