Diagrams/Dev/Gradients

From HaskellWiki

Currently, code like

linearG = ...
example = square 1 # fillTexture linearG

does not work, whereas doing something like

example = square 1 # fillTexture linearG # pad 1

does work. The difference is that in the first example, the style containing the fill texture gets commuted up past the frozen transformation applied by adjustDia2D. Given the userSpaceOnUse option, gradients take their coordinate system from the place they are referenced rather than the place they are defined, so this means that transformation gets applied to the gradient twice: once explicitly when we commute the transformation past the style, and once implicitly when the transformation is applied again because it is still above the reference to the gradient in the tree. (One complication is that the literal reference to the gradient is actually above the g transform node in the tree, but it seems perhaps it is actually looking at any path nodes which actually use the fill, although that is not clear from the SVG spec.)

However, when we commute non-frozen transforms past a gradient, we do need to apply them, since they will ultimately get absorbed into some prim and hence do not explicitly show up in the tree. So when we commute transforms down past a gradient we need to apply only non-frozen transforms. The problem is that we don't know which are frozen and which are not.

The current idea is to add a preprocessing pass which marks transforms as frozen or not. Instead of calling untangle in toDTree, we can just turn a coproduct into a linear chain of tree nodes; then we do a pass marking transforms; finally we do a pass to push transforms down and coalesce styles. We also add a new type of style node which is affected by non-frozen transforms only.

See the below IRC conversation for more context.

(10:11) < Martingal> byorgey you around
(10:12) <   byorgey> Martingale: yes
(10:13) < Martingal> byorgey What if when we `untangle` in toDTree we only apply the nonfrozen part of the transform to the style?
(10:15) <   byorgey> Martingale: no good.  Because sometimes you only have a single transformation (an 'M' node) instead of a split (:|:) and the only way to tell if it is frozen is to look for any splits below 
                     it.
(10:15) <   byorgey> which is what gets done recursively by fromDTree.
(10:16) <   byorgey> and in any case, for everything other than gradients, the frozen part of the transform *must* be applied to the style.
(10:16) <Martingale> Ah, this is a tricky one
(10:17) <Martingale> It's seems like we need information we don't yet have as we traverse the tree
(10:18) <   byorgey> right.  Which is why I've been thinking along the lines of a two-pass solution.
(10:19) <   byorgey> but I'm still not exactly sure what we should do in the second pass.
(10:21) <Martingale> would it help to have a third type of attribute - one that is only transformed by non-frozen transformations?
(10:21) *** fryguybob Wishes he could help, but he hasn't been following along.
(10:22) <   byorgey> fryguybob: don't worry about it, you should focus on the optparse stuff =)
(10:23) < fryguybob> byorgey: What? I can't hear you over the Haddock!
(10:23) <   byorgey> hahaha
(10:23) <   byorgey> Martingale: hmmm, interesting idea.
(10:24) <Martingale> fryguybob up until now it did not matter if we transfomed an object directly (transform t object) of by changing coordinates (<g transform …) but now it does becuase
(10:25) <Martingale> fryguybob changing coordinates impacts the gradient
(10:25) <   byorgey> Martingale: the problem is, again, how to tell whether a transformation is frozen or not.
(10:25) < Martingal> byorgey i thought that is what the first pass would do?
(10:26) <   byorgey> oh, I see, we could add an extra first pass that simply walks over the tree and marks transformations as frozen or non-frozen.
(10:26) <Martingale> yes
(10:27) <   byorgey> then when we go to push transformations down the tree we know what to do with each one when it commutes with a style.
(10:27) <Martingale> you think it could work?
(10:28) <   byorgey> Yes, I think it could work.  But I am not confident of our ability to implement it today and get it to work without breaking anything else.
(10:28) <Martingale> Yeah, a few different parts of the code base need to change
(10:29) <Martingale> Is there any problem when there are multiple freezes along the same path?
(10:30) <   byorgey> no, I don't think so
(10:30) <   byorgey> I mean, there might be, but I don't forsee any at the moment =)
(10:31) < Martingal> byorgey OK so to clarify, we have two parts. 1) walk the tree and mark the transforms as frozen or unfrozen. 2) add a third attribute type (semi-freddo)
(10:31) <   byorgey> right
(10:32) < travis-ci> [travis-ci] diagrams-doc/optparse 7af70da http://travis-ci.org/diagrams/diagrams-doc/builds/14122279 The build has errored.
(10:32) < Martingal> byorgey I agree that it probably can't be done today. I'm not sure how much time illl have today.
(10:33) <   byorgey> (1) is tricky though because currently in toDTree we call 'untangle', at which point it is already too late, because untangle might commute a transformation up past a style.
(10:33) <   byorgey> so we would have to change the way toDTree works so it doesn't call untangle, i.e. we get an even more "raw" form of DTree
(10:34) <   byorgey> then we do the freeze-mark pass, then we untangle and stuff, and then we convert to RTree by pushing transforms down and so on
(10:35) <   byorgey> and this is complicated enough that I also want to spend more time thinking about it to make sure there isn't a simpler solution.
(10:35)                -!- jbracker [~quassel@m-116.informatik.uni-kiel.de] has joined #diagrams
(10:35) < Martingal> byorgey Good idea, before we plunge ahead we should think some more, but at least we have a fall back
(10:36) <   byorgey> right
(10:37) <   byorgey> so sadly it looks to me like gradients will have to wait until after 1.0
(10:37) < fryguybob> :(
(10:37) <Martingale> :(
(10:37) <   byorgey> :(
(10:37) < fryguybob> 1.1 :D
(10:38) <Martingale> One thing I want to think through (you guys might already have) is what would happened if we took the opposite approach to making RTrees transfromable
(10:38) <   byorgey> Martingale: OK
(10:39) <Martingale> That is - make nothing transformable and do it all with coordinate change (<g transform) or (cairTransf)
(10:39) <   byorgey> Martingale: hmmm
(10:41) <   byorgey> well, I think that would solve our problem with gradients (*IF* I have understood correctly how that works---of which I am not confident) --- we could just make gradients non-transformable.
(10:42) <   byorgey> since they will pick up whatever <g transform> nodes are in the tree anyway.
(10:42) < travis-ci> [travis-ci] diagrams-contrib/master 32eac63 http://travis-ci.org/diagrams/diagrams-contrib/builds/14087209 The build passed.
(10:42) <   byorgey> the downside is that without some changes to the way we do things, it would bloat the SVGs
(10:43) <Martingale> that's for sure
(10:43) <   byorgey> e.g. doing  (hcat $ replicate 100 (circle 1)) # scale 2   would result in 100 <g transform> nodes above the circle prims
(10:43) <   byorgey> actually, even worse, since a circle is 4 prims
(10:44) <   byorgey> now, we could certainly do some extra work to avoid pushing transforms lower than necessary
(10:44) < travis-ci> [travis-ci] diagrams-svg/gradient 5d11e7c http://travis-ci.org/diagrams/diagrams-svg/builds/14087271 The build passed.
(10:44) <   byorgey> but it would mean some reworking of toRTree and so on
(10:45) <   byorgey> oh, wait, never mind, this wouldn't work
(10:45) <   byorgey> putting all the transforms in <g transform> nodes directly would mean they all act like frozen transforms as far as things like line width is concerned
(10:46) <   byorgey> so that would actually give us the wrong semantics.
(10:46) <Martingale> That was my main concern - we would need a different way to handle line withs
(10:47) <   byorgey> Right, but I don't know of any other way to do it.
(10:47) <   byorgey> we could do it if we were willing to give up the ability to apply non-uniform frozen scales and have it result in e.g. thinner and thicker lines
(10:48) <   byorgey> because then we could just compute an average scale change from a transform and modify the line width directly.
(10:48) <   byorgey> however, I could be wrong --- there might be other ways to do it.  We would have to carefully study the PS and SVG specs.
(10:48) <Martingale> That's why i said i want to think it through? there is a lot to think about
(10:49) <   byorgey> and pray to Mozilla that it is implemented correctly
(10:49) <   byorgey> yep.
(10:49) <   byorgey> anyway, I will write something up on the wiki today summarizing all of this, so we won't forget
(10:49) <Martingale> yes - so far the implementation of SVG seems pretty good, it's the documentation i cant stand
(10:50) <   byorgey> yeah, it's not great
(10:50) <Martingale> That would be awesome, thanks - i have to run. talk to you later.
(10:50) <   byorgey> OK, later