Adding clippaths to the Ps/Pdf exporters
Hi,
I am in need some advice and suggestions from an extensions expert..
I would like to improve the pdf exporter by handle clippaths (and maybe later masks), but I am having a hard time figuring out how I best can go about to add such features. ( There is no code for this in the postscript exporter that I can copy :-)
Should it be possible to continue using a "print" extension or do I need to start use an "output" extension for this? I understand that an output extension is handed the full document tree at once. A print extension on the other hand is given a single path at a time together with the needed style, transformation matrix, bounding box, and so on. But I don't see if and how a print extension can get information about the needed clipping path.
If there is no information about the clippath available for print extensions would it be okay to add this (by changing the interface)? Is it then better with a new set_clippath method or an extra clippath parameter for the fill and stroke methods?
Ulf
On Wed, Aug 09, 2006 at 03:45:04PM +0200, Ulf Erikson wrote:
Hi,
I am in need some advice and suggestions from an extensions expert..
I would like to improve the pdf exporter by handle clippaths (and maybe later masks), but I am having a hard time figuring out how I best can go about to add such features. ( There is no code for this in the postscript exporter that I can copy :-)
Should it be possible to continue using a "print" extension or do I need to start use an "output" extension for this? I understand that an output extension is handed the full document tree at once. A print extension on the other hand is given a single path at a time together with the needed style, transformation matrix, bounding box, and so on. But I don't see if and how a print extension can get information about the needed clipping path.
Sounds like you probably want to switch to using an "output" extension.
If there is no information about the clippath available for print extensions would it be okay to add this (by changing the interface)? Is it then better with a new set_clippath method or an extra clippath parameter for the fill and stroke methods?
Maybe... I don't really follow what you mean; can you describe it a bit more?
Offhand, I'd say go ahead and try it. We usually encourage people to "patch first, discuss later" since it's usually easier to decide if something is the right way, after there is some tangible code to try out.
Bryce
Bryce Harrington wrote:
On Wed, Aug 09, 2006 at 03:45:04PM +0200, Ulf Erikson wrote:
I would like to improve the pdf exporter by handle clippaths
Should it be possible to continue using a "print" extension or do I need to start use an "output" extension for this? I understand that an output extension is handed the full document tree at once. A print extension on the other hand is given a single path at a time together with the needed style, transformation matrix, bounding box, and so on. But I don't see if and how a print extension can get information about the needed clipping path.
Sounds like you probably want to switch to using an "output" extension.
Well.. I guess that way I would have all information at hand, but it also looks more complicated to even get started. If it is not needed I prefer to stay with a print extension
Maybe I was hoping there would be a magic sp_get_current_clippath() function of some kind. I keep finding new functions that manage to dig out the information I am looking for. But there is no chance on this one? ;-)
If there is no information about the clippath available for print extensions would it be okay to add this (by changing the interface)? Is it then better with a new set_clippath method or an extra clippath parameter for the fill and stroke methods?
Maybe... I don't really follow what you mean; can you describe it a bit more?
I'll try..
I think a reference to the clippath to be used on a path is held in clip_ref of SPItem. The fill() and stroke() functions of a print extension are called from sp_shape_print() in sp-shape.cpp. This is an excerpt of the current code:
if (style->fill.type != SP_PAINT_TYPE_NONE) { NRBPath bp; bp.path = SP_CURVE_BPATH(shape->curve); sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox); }
Adding the clippath as a parameter to fill() seems like a minor change (maybe like this?)
if (style->fill.type != SP_PAINT_TYPE_NONE) { NRBPath bp; bp.path = SP_CURVE_BPATH(shape->curve); SPClipPath *cp = item->clip_ref->getObject(); sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox, cp); }
This would be easy enough and straight forward, but.. I guess you can use a clippath on a group of paths and that would lead to quite some duplicate definitions of the same clip path. It might thus be better to have a function pair like: sp_print_set_clippath( item->clip_ref->getObject() ); and sp_print_release_clippath(); in a way similar to the bind/release pair for transformations. I'm still not sure where those two would have to be added though..
The next idea is new and not thought through.. maybe the clippath push and pop could even be added to the current bind/release functions?
Offhand, I'd say go ahead and try it. We usually encourage people to "patch first, discuss later" since it's usually easier to decide if something is the right way, after there is some tangible code to try out.
Okay, but I am still interested in hearing more ideas and suggestions. When/if I have something to show you will find it in the patch tracker.
Ulf
Mental, what are your thoughts on this approach?
On Wed, Aug 09, 2006 at 09:44:37PM +0200, Ulf Erikson wrote:
Bryce Harrington wrote:
On Wed, Aug 09, 2006 at 03:45:04PM +0200, Ulf Erikson wrote:
I would like to improve the pdf exporter by handle clippaths
Should it be possible to continue using a "print" extension or do I need to start use an "output" extension for this? I understand that an output extension is handed the full document tree at once. A print extension on the other hand is given a single path at a time together with the needed style, transformation matrix, bounding box, and so on. But I don't see if and how a print extension can get information about the needed clipping path.
Sounds like you probably want to switch to using an "output" extension.
Well.. I guess that way I would have all information at hand, but it also looks more complicated to even get started. If it is not needed I prefer to stay with a print extension
Maybe I was hoping there would be a magic sp_get_current_clippath() function of some kind. I keep finding new functions that manage to dig out the information I am looking for. But there is no chance on this one? ;-)
If there is no information about the clippath available for print extensions would it be okay to add this (by changing the interface)? Is it then better with a new set_clippath method or an extra clippath parameter for the fill and stroke methods?
Maybe... I don't really follow what you mean; can you describe it a bit more?
I'll try..
I think a reference to the clippath to be used on a path is held in clip_ref of SPItem. The fill() and stroke() functions of a print extension are called from sp_shape_print() in sp-shape.cpp. This is an excerpt of the current code:
if (style->fill.type != SP_PAINT_TYPE_NONE) { NRBPath bp; bp.path = SP_CURVE_BPATH(shape->curve); sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox); }
Adding the clippath as a parameter to fill() seems like a minor change (maybe like this?)
if (style->fill.type != SP_PAINT_TYPE_NONE) { NRBPath bp; bp.path = SP_CURVE_BPATH(shape->curve); SPClipPath *cp = item->clip_ref->getObject(); sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox, cp); }
This would be easy enough and straight forward, but.. I guess you can use a clippath on a group of paths and that would lead to quite some duplicate definitions of the same clip path. It might thus be better to have a function pair like: sp_print_set_clippath( item->clip_ref->getObject() ); and sp_print_release_clippath(); in a way similar to the bind/release pair for transformations. I'm still not sure where those two would have to be added though..
The next idea is new and not thought through.. maybe the clippath push and pop could even be added to the current bind/release functions?
Offhand, I'd say go ahead and try it. We usually encourage people to "patch first, discuss later" since it's usually easier to decide if something is the right way, after there is some tangible code to try out.
Okay, but I am still interested in hearing more ideas and suggestions. When/if I have something to show you will find it in the patch tracker.
Ulf
On Wed, 2006-08-09 at 12:46 -0700, Bryce Harrington wrote:
Mental, what are your thoughts on this approach?
Hmm, I don't know. I think the printing API needs to expose clippaths somehow anyway, so we may as well augment that rather than moving everything over to the "output" API. (At some point we'll also need to consider whether we can merge the two APIs, though...)
Since clippaths accumulate (via intersection) from parent to child, so it probably is something we should make part of the state that is push/popped.
-mental
MenTaLguY wrote:
Hmm, I don't know. I think the printing API needs to expose clippaths somehow anyway, so we may as well augment that rather than moving everything over to the "output" API. (At some point we'll also need to consider whether we can merge the two APIs, though...)
I think that the output extension is actually the "correct" one to use. They are the ones shown in the SaveAs dialog. The ps, pdf and some more exporters have two extensions; one output extension that includes a full copy of sp_print_document_to_file() only to be able to chose another printer context than the default postscript printer; and one print extension that actually writes the file.
How about building an output extension that implements the print extension interface? Other extensions could then inherit this funtionality and let you write an output extension by using the simpler print extension interface.
Now, this would probably be simpler to do if there was an SPShape::print() instead of the sp_shape_print().. and the same for all other SPItem items
Since clippaths accumulate (via intersection) from parent to child, so it probably is something we should make part of the state that is push/popped.
Isn't the print extension mainly for printing to postscript? If both postscript and pdf are able to intersect clip paths there wouldn't be a need to keep that in the state. It would be enough to tell when to push/pop a clip path. What do you think of adding such a push/pop pair for the clip path in sp_item_invoke_print()? (since the clip path is already handled in sp_item_invoke_show()).
On Thu, 2006-08-10 at 16:46 +0200, Ulf Erikson wrote:
Isn't the print extension mainly for printing to postscript? If both postscript and pdf are able to intersect clip paths there wouldn't be a need to keep that in the state. It would be enough to tell when to push/pop a clip path.
Well, the way that it works in Postscript level <= 2 is that the clipping path is simply part of the gstate. There's a 'clip' operator (and an 'eoclip' variant for the even-odd fill rule) which computes the intersection of the current path and the current clipping path and makes that the new clipping path. If you want to save and restore the clipping path, that has to happen as part of saving and restoring the gstate as a whole.
Postscript Level 3 does introduce 'clipsave' and 'cliprestore' operators, but for our purposes I think it might actually be preferable to stick with saving and restoring via the gstate, since we're doing it anyway.
What do you think of adding such a push/pop pair for the clip path in sp_item_invoke_print()? (since the clip path is already handled in sp_item_invoke_show()).
That seems reasonable.
-mental
I've got a first patch for exporting clip-paths to Ps and Pdf now. http://sourceforge.net/tracker/index.php?func=detail&aid=1539297&gro...
The patch allows some clip-paths to be exported to Ps and Pdf files. Only a single simple shape or a single group of simple shapes (all with the same wind rule) can be used as clip-path.
MenTaLguY wrote:
Well, the way that it works in Postscript level <= 2 is that the clipping path is simply part of the gstate. There's a 'clip' operator (and an 'eoclip' variant for the even-odd fill rule) which computes the intersection of the current path and the current clipping path and makes that the new clipping path. If you want to save and restore the clipping path, that has to happen as part of saving and restoring the gstate as a whole.
That's the functions I have used. I've noticed that this technique does have a number of limitations.. Some might be overcome, but I don't think all clip-paths can be exported this way
You can of course intersect any number of clip paths: newpath path.1 clip newpath path.2 clip
And it is also possible to make a union of paths to clip with: newpath path.1 path.2 clip
BUT with only a single 'clip' command the shapes in a union will all be either winding or not. I see no way to have a union of winding and non-winding paths as a clip path.
Next issue are groups within a group. Their contents should be made union with all single shapes in the group. I didn't code this, but think it should be possible if someone feels like it.
Another one is the use of a clipped shape as a clip path. That would make a second clip path (an intersection) which sounds possible if the clipped is the whole clip-path, but what if this clipped shape sat in a group with other shapes? I don't think that is translatable to ps/pdf vectors.
Let me know what you think
participants (3)
-
Bryce Harrington
-
MenTaLguY
-
Ulf Erikson