What could a perl developer do to help? I can also do graphics design but I dout that will be of help either.
On Sat, 18 Mar 2006 19:09:08 -0400 , "bulia byak" <buliabyak@...400...> wrote:
For those interested, below is the implementation plan for the live path effects that Aaron, Mental and I have developed. It's pretty simple and powerful, we just need more volunteers to work on it. It's currently in a branch in SVN.
STAGE 1 is documented in a jabber chat from 2005-10-10. It is already implemented in the branch and seems to work fine (last time I checked, anyway).
[19:01:50] <bbyak> well, i think the first thing you should do is familiarize yourself with SPCurve and Bpath classes [19:02:16] <bbyak> i guess for you they will be obvious, just another array of lineto/moveto/curvetos [19:04:00] <bbyak> then, write a simple spcurve->spcurve distortion function [19:04:09] <bbyak> any kind of distortion, just to check [19:04:52] <bbyak> make it a member of SPShape [19:05:26] <ACSpike> so the goal is to distort nartbpath [19:05:40] <bbyak> yes, as a start [19:05:52] <ACSpike> by way of spcurve [19:06:09] <ACSpike> and stick it in sp-shape [19:06:15] <bbyak> yes [19:06:16] <bbyak> then: [19:06:47] <bbyak> declare a bunch of attribs: inkscape:original-d and as many attrs as needed to express your distortion [19:06:50] <ACSpike> I don't understand how I will test this function [19:06:57] <bbyak> i'll explain that now [19:07:15] <bbyak> attribs are declared in attributes.h/cpp i think [19:07:33] <bbyak> then learn the way an SPObject reads attrs from the repr [19:07:36] <bbyak> it's simple: [19:07:52] <bbyak> for example sp-path.cpp [19:08:21] <bbyak> sp_path_build calls sp_object_read_attr for all attributes it knows [19:08:33] <bbyak> thoese calls end up in sp_path_set [19:09:01] <bbyak> which is where you do the necessary changes based on the attribute string passed to you [19:09:11] <bbyak> similar functions are in all other SPObjects [19:09:34] <ACSpike> "necessary changes" = distort path [19:09:40] <bbyak> we'll start by sp-path [19:09:41] <bbyak> yes [19:09:44] <bbyak> namely: [19:10:05] <bbyak> you'll need to add another member, a boolean flag in SPShape class [19:10:20] <bbyak> which if set means that this shape is distorted [19:10:42] <bbyak> and also you'll need one or more members for storing the distortion params [19:10:47] <ACSpike> oh, wife calls, brb. [19:11:16] <bbyak> then in sp_path_build you add another sp_object_read_attr for the distortion attribs [19:11:43] <bbyak> and in sp_path_set, a new case for those attrs [19:12:19] <bbyak> where you just parse and store the value in the (SPShape *) path, i.e. this path recast to shape [19:12:35] <bbyak> and set the "distorted" flag [19:13:02] <bbyak> those new sp_object_read_attr must go before the sp_object_read_attr for d= [19:13:30] <bbyak> then you add a sp_object_read_attr for inkscape:original-d [19:13:41] <bbyak> where you do the same as in case SP_ATTR_D: [19:13:58] <bbyak> but insert a call to the distortion function [19:14:12] <bbyak> after sp_svg_read_path(value); [19:14:32] <bbyak> then you set that distorted curve as usual, sp_shape_set_curve [19:14:47] <bbyak> and then one last thing: [19:15:41] <bbyak> the sp_object_read_attr for d= must go AFTER that for original-d, and in it, if the distorted flag is set, you simply skip reading the d and setting the curve [19:15:46] --- mental has left [19:16:08] <bbyak> so that the curve is obtained from orioginal-d with distortion, when they are present [19:16:47] <bbyak> that's all for stage 1, i think [19:17:10] <bbyak> it should work if you manually add the attrs to a path and it will show it distorted [19:17:19] <bbyak> and will be generally very instructive to play with [19:17:33] <bbyak> based on which, it will be more clear where to go next
STAGE 2 is not done yet, I documented it in a message to Aaron:
Overall, our Stage II goals are:
- make the system capable of handling several different effects,
with new ones easy to add
- make sure effects are correctly read in SPPath and in all
shapes
make sure objects with effects are correctly transformed
make sure paths with effects are correctly node-edited
make sure shapes with effects are correctly handle-edited
make sure objects with effects are correctly written and
rendered the same in Batik
Most of these goals are surprisingly easy to achieve :) So don't be frightened by the length of this email - it's just wordy explanations.
After all this works, we can move on to implementing the Path Effects tool and handle-dragging UI for editing effects on canvas... that will be Stage III.
Now, the goals in detail:
- Rename inkscape:distorted into inkscape:path-effect. This
attribute would store a string identifier of the effect to apply, or "none". If there's no such attribute, it's the same as "none". In addition, register several attributes for distortion parameters:
inkscape:path-effect-param1 inkscape:path-effect-param2 inkscape:path-effect-param3
etc. The interpretation of these will of course depend on the value of inkscape:path-effect.
Then, move the reading of these attributes into SPShape, as they will be used by all its subclasses (not only SPPath but also shapes) in the same way. (That is, sp_object_read_attr(object, "inkscape:path-effect") etc must also be in sp_shape_build.) Store the values in appropriate new members of SPShape. Write a generic function that takes SPCurve and a SPShape pointers and distorts the SPCurve according to the values of the members of SPShape. Store that function in sp-shape.cpp and declare in sp-shape.h so that it can be used from outside.
You can even code a couple useful effects at this stage :)
- For SPPath, it's all ready: it reads original-d, distorts it
and sets the curve from that. In shapes, it's even simpler. Take SPStar for an example. In sp-star.cpp, find the line
sp_shape_set_curve_insync (SP_SHAPE (star), c, TRUE);
and just insert the call to the distortion function in sp-shape before that, passing it the curve and SP_SHAPE (star). That is all! Shapes have no need for original-d because their path is generated from the shape parameters anyway.
- Transforming objects works like this. In "preserve" mode (see
Inkscape Prefs), a transform= attribute is added or edited on all transformed objects. In the "optimize" mode (which is the default), various types of objects variously try to embed the transform, or a component thereof. If this is not possible, again, transform= attribute is added. For example, for paths, sp_path_transform can completely embed all of the transform into its curve (i.e. into d=), by transforming each path point by that matrix, so it returns identity and transform= is not set. For rects, sp_rect_set_transform embeds only translation and scaling components of the matrix; the remainder, if any, is written as transform=. For stars and ellipses, no embedding is attempted at all, so the whole transform is always written as transform=.
Now, for paths, sp_path_transform currently transforms the (SPShape*)path->curve, i.e. the distorted curve stored in base SPShape instance. But we also need to transform the original path by the same matrix too, so that it stays in sync. The easiest way to do this, which will also have other benefits, is to store the original path in SPPath as another SPCurve. That is, (SPShape*)path->curve will be the distorted path, while (SPPath*)path->original_curve will store the original path.
You will thus need to add this member in sp-path.h and to add to store the original SPCurve before distortion in that member in sp_path_set, case SP_ATTR_ORIGINAL_D. (You may need to figure out how to copy SPCurves and/or bpaths. Also don't forget to free the SPCurve when destroying the path in sp_path_release.) Then look at sp_path_transform:
/* Transform the path */ NRBPath dpath, spath; spath.path = shape->curve->bpath; nr_path_duplicate_transform(&dpath, &spath, xform); SPCurve *curve = sp_curve_new_from_bpath(dpath.path); if (curve) { sp_shape_set_curve(shape, curve, TRUE); sp_curve_unref(curve); }
And just do the same also for your original SPCurve stored in SPPath. That is all.
For shapes, you normally don't need to do anything at all. Those that don't attempt any embedding and always use transform= attribute are not affected at all. Those that do embed do it just by adjusting their internal shape parameters and regenerating the curve - for example sp_rect_set_transform calls sp_rect_set_shape(rect). Provided you inserted a distortion call into *_set_shape, you are all set.
CAVEAT: rects are the only shape which currently uses <rect>, not <path>. So you cannot apply shape effects to rects at all, until this is changed. It's on my TODO for a long time, hope I will get a round tuit soon.
- The Inkscape::NodePath::Path reads the path from SPCurve, but
after modifying it, it writes directly to the d= attribute. This needs to be changed thus: (a) if the path is distorted, read the SPCurve from SPPath, not from SPShape (i.e. the original, not the distorted one), and (b) if the path is distorted, write the edited path to inkscape:original-d= instead of d= (in update_repr_internal). Setting inkscape:original-d will trigger reading it and setting both original and distorted curves, the latter in turn triggering a redisplay of the distorted path. So I think this will be enough for nodepath to edit the source path, with the nodes generally not lying on the visible distorted path. Adding a helper display of the original path between nodepath nodes can be left for later.
- I think here nothing at all is needed. The knotholder thing
reads and writes from the shape's internal parameters, and thus is totally unaffected by the visible distorted path.
- Look at sp_path_write: it writes the d= attribute from
(SPShape*)path->curve, that is, from the distorted path. So the "same display in Batik" part is already taken care of. We only need to write the original-d so it stays in sync. Just repeat this block:
if ( shape->curve != NULL ) { NArtBpath *abp = sp_curve_first_bpath(shape->curve); if (abp) { gchar *str = sp_svg_write_path(abp); sp_repr_set_attr(repr, "d", str); g_free(str); } else { sp_repr_set_attr(repr, "d", ""); } } else { sp_repr_set_attr(repr, "d", NULL); }
but for path->original_curve and the inkscape:original-d attribute, and you are all set.
For shapes, again, nothing needs to be done. Except for rects, shapes' _write methods (e.g. sp_star_write) create <path> element and set its d= from the SPShape curve. This is just what we need.
That is all - as you see, it's all quite simple, logical and fits neatly. There will be gotchas of course, but overall the system looks quite straightforward and robust. I'm really excited by this.
-- bulia byak Inkscape. Draw Freely. http://www.inkscape.org
This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid%110944&bid$1720&dat%... _______________________________________________ Inkscape-devel mailing list Inkscape-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/inkscape-devel