[Chart] Fwd: [diagrams] Re: [GSoC 2013] Progress - Porting Charts to Diagrams

Jan Bracker jan.bracker at googlemail.com
Wed Jul 10 11:12:32 BST 2013


Hello everybody,

thanks for your input on the flags Brent! I no used them to steer separate
compilation in the test package.

What changed during the last week:
- I fixed the 'PickFn' returns I accidentally removed. They now work as
before and I restored them everywhere I removed them.
- I removed a lot of unused language extensions.
- The packages are now named according to the scheme set by the Chart and
Chart-gtk package.
- Utility functions for implementing backends are now in the Backend.Utils
module.
- As suggested I removed the splitbase flag from all packages.
- Each executable in the Chart-test package has to be activated by a flag
now.
- I fixed some bugs. Most important a bug that transformations are applied
in the wrong order.

The latest "stable" version can be found here [0].

Aside from this work I completed an alternate implementation of the backend
interface, based on a deep embedding instead of a type class. This worked
perfectly and removes the necessity of the additional type parameter in
many types. This alternate implementation can be seen in the 'deep-backend'
branch of my fork [1]. I also noticed that this alternate implementation
can give implementors a better infrastructure to implement backends. This
can be seen in the Backend.Utils module [2].

Greets
Jan

[0]:
https://github.com/jbracker/haskell-chart/tree/1228afaba503509c58c7bfa079c946be03089bdf
[1]: https://github.com/jbracker/haskell-chart/tree/deep-backend
[2]:
https://github.com/jbracker/haskell-chart/blob/deep-backend/chart/Graphics/Rendering/Chart/Backend/Utils.hs


2013/7/2 Brent Yorgey <byorgey at seas.upenn.edu>

> Whoops, looks like my email got munged a bit.  The parenthetical in
> the middle was supposed to say
>
>   ("default" means how the flag is set if the user does not explicitly
>   specify; "manual" means that the cabal solver should not
>   automatically try toggling the flag when creating a build plan,
>   i.e. the flag should be changed only by the user.)
>
> -Brent
>
> On Tue, Jul 02, 2013 at 07:56:53AM -0400, Brent Yorgey wrote:
> > On Tue, Jul 02, 2013 at 11:17:57AM +0200, Jan Bracker wrote:
> > >
> > > It seems like cabal does not support the separate compilation of
> > > executable. So we have to split the test package to manage
> dependencies.
> >
> > That's not true.  (Assuming I understand what you are saying.)
>         You
> > can use some (standard) tricks with cabal flags         to make
>          this work.
> > For example, see the diagrams-builder package, which has several
> > executables (each with different dependencies) but you control which
> > are installed via flags, and you only incur the          dependencies of
>      the
> > ones you request to be installed.  The idea is to make a flag like
> >
> > flag cairo
> >   description: install cairo-specific builder tool
> >   default:     False
> >   manual:      True
> >
> > ("default" means how the flag is set if       the user does not
> explicitly
> > specify; "manual" means that the cabal s
> >
> > and then in the
> > executable section you make both 'buildable' and the dependencies
> > conditional on the flag, like this:
> >
> > executable diagrams-builder-cairo
> >   main-is:             diagrams-builder-cairo.hs
> >   hs-source-dirs:      src/tools
> >   default-language:    Haskell2010
> >   other-extensions:    DeriveDataTypeable
> >                        RecordWildCards
> >
> >   if !flag(cairo)
> >     buildable: False
> >
> >   if flag(cairo)
> >     build-depends:     base >= 4 && < 5,
> >                        filepath,
> >                        directory,
> >                        diagrams-builder,
> >                        diagrams-lib >= 0.6 && < 0.7,
> >                        diagrams-cairo >= 0.6 && < 0.7,
> >                        cmdargs >= 0.6 && < 0.11
> >
> > When building, if you want to turn on a specific flag you do something
> like
> >
> >   cabal install -fcairo diagrams-builder
> >
> > -Brent
> >
> > >
> > > The most current stable version of the port can be found here [0] in
> > > commit 2e2277b4a65dc426d2da2a92b4c27eaa6bc11ecd .
> > >
> > > Greets
> > > Jan
> > >
> > > [0]:
> > >
> https://github.com/jbracker/haskell-chart/tree/2e2277b4a65dc426d2da2a92b4c27eaa6bc11ecd
> > >
> > >
> > > 2013/6/25 Jan Bracker <jan.bracker at googlemail.com>
> > >
> > > > Hello everybody,
> > > >
> > > > the last week brought some major changes. The current stable version
> is
> > > > here [0]. All changes are in the master branch of my fork. What has
> been
> > > > done / changed:
> > > >
> > > > - Implemented a new type for 'Path' that supports to be closed. Like
> this
> > > > 'fillPath' and 'strokePath' do not need a boolean flag anymore. This
> should
> > > > also make future changes easier, since the 'Path' type is abstract.
> > > > - Cleaned up the code and added documentation for the 'Backend',
> > > > 'Geometry' and 'Drawing' functions.
> > > > - 'withClipRegion' now works in a hierarchical manner. You can only
> make
> > > > the clipping region smaller and you can only clip on areas in your
> current
> > > > clip. The clip region is represented by a 'Limit Rect'. This properly
> > > > reflects the possibilities that the clip region can be empty 'LMin'
> or an
> > > > infinite plane 'LMax'.
> > > > - Removed the associated 'ChartOutput' type from the 'ChartBackend'
> class.
> > > > Instead backend modules now deliver functions specific to their
> backend.
> > > > - Removed all function with legacy names and switched the complete
> library
> > > > to use the new API and functions.
> > > > - Marked all 'default...' values as deprecated to push the
> transition to
> > > > Data.Default.
> > > > - Removed the 'Types' module again and distributed all contents into
> > > > 'Backend', 'Geometry' and 'Drawing'.
> > > > - Moved the cairo backend and the tests to their own packages (
> > > > chart-cairo and chart-tests ).
> > > > - Updated/Fixed the 'chart-gtk' package to work together with all
> changes.
> > > > Its tests are now also in the chart-tests package.
> > > >
> > > > Some questions that I have:
> > > >
> > > > - When implementing the new version of 'withClipRegion' I stumbled
> upon
> > > > the question how the empty clip region looks in cairo. Right now I
> use the
> > > > empty 'Rect' at location (0,0) to represent this. This seems to work
> fine.
> > > > - Right now the 'Renderable' class is commented out. Should I try to
> > > > reintroduce it? Is this really a good Idea or should we leave it
> away all
> > > > together? None of Charts uses it anymore.
> > > >
> > > > My plan for the next week would be:
> > > >
> > > > - Implement a test that only uses the backend API so we have
> something
> > > > more basic to check if the backends work as expected. This will also
> show
> > > > if the current documentation is specific enough.
> > > > - Try to bring 'Renderable' back into scope (If that is a good idea)
> > > >
> > > > The next big step after this would be to merge all the changes back
> into
> > > > the main Charts repository and start developing the Diagrams backend.
> > > >
> > > > Greets
> > > > Jan
> > > >
> > > > [0]:
> > > >
> https://github.com/jbracker/haskell-chart/tree/dcd35c767c69db40e1494608029736ae60148378
> > > >
> > > >
> > > > 2013/6/17 Jan Bracker <jan.bracker at googlemail.com>
> > > >
> > > >> Hello everybody,
> > > >>
> > > >> I made good progress over the last week. I implemented the minimal
> chart
> > > >> drawing API (  http://hpaste.org/89758 ) that Tim suggested. It
> worked
> > > >> with minor problems. I tried to stay pixel equal to the PNGs that
> the
> > > >> current release produces when running the test suite. I did not
> manage to
> > > >> stay 100% pixel equal, but all differences are not visible with the
> naked
> > > >> eye.
> > > >>
> > > >> Here the changes I had to apply to the API:
> > > >>
> > > >> - TextSize also contains the Y-bearing since it is used in some of
> the
> > > >> text adjustment calculations.
> > > >> - withSourceColor does not exists any more. The line style provides
> the
> > > >> color for stroking, fill style the color for filling and font style
> the
> > > >> color for fonts. There are several utilities to aid implementors of
> > > >> backends with keeping the local environment up to date.
> > > >> - The strokePath and fillPath functions are now backendStrokePath
> and
> > > >> backendFillPath. They take an extra parameter that tells them if
> the given
> > > >> path shall be close before rendering. This was necessary to produce
> equal
> > > >> output. Convenience functions that default to not closed paths are
> provided.
> > > >> - The matrix implementation is basically a copy of the matrix
> > > >> implementation from cairo.
> > > >> - The withClipRegion function now takes a Maybe Rect. I thought this
> > > >> might be useful, because otherwise there would be no possibility to
> remove
> > > >> the clip region. Though this is not needed anywhere in charts yet.
> > > >> - I had to add the fillClip function, because otherwise there would
> have
> > > >> been no possibility to fill the clip region if it is not set
> (infinite
> > > >> plane clip).
> > > >> - showText is now drawText and also takes a Point so it know where
> to
> > > >> draw the text. The point refers to the left end of the text
> baseline.
> > > >> - The drawing module now contains all kinds of higher level drawing
> > > >> functions and helpers. There are still a lot of legacy functions
> with
> > > >> temporary names. I will remove these soon.
> > > >>
> > > >> This commit is "stable" [0]:
> bdb628591132964e94f5b317026605790250359a
> > > >>
> > > >> Plans I would like to hear thoughts to:
> > > >>
> > > >> - Should I prefix the backend functions and provide wrapper
> functions
> > > >> with the nice name? I already did this for backendFillPath since I
> noticed
> > > >> that it also needed to know if the path has to be closed, but in
> 95% of all
> > > >> cases the version that does not close by default is more practical.
> Like
> > > >> this we would also be able to change the backend interface without
> having
> > > >> to change several other modules.
> > > >> - Should I keep the Maybe in withClipRegion? As said nothing in
> charts
> > > >> actually ever removes the clip region.
> > > >>
> > > >> The next steps would be:
> > > >>
> > > >> - Remove legacy functions.
> > > >> - Document all the drawing functions.
> > > >> - Create a separate package for the Cairo backend. I don't know if
> we
> > > >> should merge with the main repo before this or afterwards.
> > > >> - There are still some direct connections to the Cairo backend in
> > > >> Simple.Internal we have to think about how these can be removed.
> > > >> - I would also suggest to create a separate package for the tests
> since
> > > >> that would make dependency management easier.
> > > >>
> > > >> Greets
> > > >> Jan
> > > >>
> > > >> [0]:
> > > >>
> https://github.com/jbracker/haskell-chart/tree/bdb628591132964e94f5b317026605790250359a
> > > >>
> > > >>
> > > >> 2013/6/13 Jan Bracker <jan.bracker at googlemail.com>
> > > >>
> > > >>> I will proceed with 3 then.
> > > >>>
> > > >>>
> > > >>> 2013/6/12 Tim Docker <tim at dockerz.net>
> > > >>>
> > > >>>>  Hi,
> > > >>>>
> > > >>>> I think your analysis is good. In the context of the backend, it
> makes
> > > >>>> sense to separate out the color from the various styles.
> > > >>>>
> > > >>>> On the other hand, in the context of the chart use API, it makes
> sense
> > > >>>> to have all of the properties of a line in a single data type -
> it's
> > > >>>> simpler for the caller to say style this plot line using
> properties as per
> > > >>>> this value.
> > > >>>>
> > > >>>> Possible solutions are:
> > > >>>>
> > > >>>>     1) Leave it and put up with the inconsistency...
> > > >>>>     2) Have separate types in the backend API / user API for
> LineStyle,
> > > >>>> FillStyle and FontStyle
> > > >>>>     3) Remove withSourceColor from the backend API, and require
> > > >>>> backends to give the logical behaviour (ie setting the FillStyle
> doesn't
> > > >>>> affect the color of lines). This would mean the cairo backend
> would have to
> > > >>>> do a bit more work to be correct.
> > > >>>>
> > > >>>> Either 2 or 3 is ok with me.
> > > >>>>
> > > >>>> Tim
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> On 13/06/13 00:45, Jan Bracker wrote:
> > > >>>>
> > > >>>> Hi everybody,
> > > >>>>
> > > >>>>  a small follow up: While thinking about and implementing the
> smaller
> > > >>>> API I noticed that due to the internals of Cairo the source color
> is used
> > > >>>> to render everything. When setting a style (font, fill, line) the
> source
> > > >>>> color is changed according to that style. This means each of the
> > > >>>> "with...Style" or "withSourceColor" functions constantly
> overrides the
> > > >>>> source color. Is this really desired behaviour? Shouldn't the
> fill color
> > > >>>> apply to fills, the line color to strokes and the font color to
> text
> > > >>>> rendering? If so the source color ("withSourceColor") is a
> useless concept.
> > > >>>> Of course keeping these color seperate will expand the cairo
> rendering
> > > >>>> backend, but I think it is useful to avoid confusion to which
> color is used
> > > >>>> where.
> > > >>>>
> > > >>>>  Example:
> > > >>>>
> > > >>>>  1: withLineStyle ls $ withFillStyle fs $ fillPath p >>
> strokePath p
> > > >>>>
> > > >>>>  should be the same as (according to my thoughts):
> > > >>>>
> > > >>>> 2: withFillStyle fs $ withLineStyle ls $ fillPath p >> strokePath
> p
> > > >>>>
> > > >>>>  but with the current implementation 1 would render both with the
> fill
> > > >>>> color and 2 would render them with the line color.
> > > >>>>
> > > >>>>  Jan
> > > >>>>
> > > >>>>
> > > >>>>
> > > >>>> 2013/6/12 Jan Bracker <jan.bracker at googlemail.com>
> > > >>>>
> > > >>>>> Hi everybody,
> > > >>>>>
> > > >>>>>  Brent: Thanks you for the offer and thanks for your great help
> on
> > > >>>>> those nasty type errors yesterday.
> > > >>>>>
> > > >>>>>  On IO in Diagrams: We looked into the SVGFont rendering stuff
> and
> > > >>>>> noticed that it has a call to unsafePerformIO (which let us
> scream in pain
> > > >>>>> and agony :-P ). We though it would be nice to remove this
> hidden call and
> > > >>>>> actually offer a function that makes it explicit. I am not sure
> why it is
> > > >>>>> there and assume its purpose is to keep everything pure. Your
> suggestion to
> > > >>>>> produce a IO Diagram is what we thought of too. We are not sure
> which
> > > >>>>> changes would be required up to now, but we will come back to
> you when we
> > > >>>>> do know.
> > > >>>>>
> > > >>>>>  On general note: I have worked on abstracting the backend the
> last
> > > >>>>> two days. Here what I accomplished by now:
> > > >>>>>
> > > >>>>>  - I have fully converted my branch to use the abstract rendering
> > > >>>>> backend ChartBackend [0] instead of the CRender monad directly.
> > > >>>>>
> > > >>>>>  - There is a implementation of the backend with Cairo in the
> > > >>>>> Backend.Cairo module [1].
> > > >>>>>
> > > >>>>>  - The current HEAD of the backend-experiment branch [2] is
> stable
> > > >>>>> (commit ad715c4d216e8fcb494f9919d4fb5459ce7d85c2).
> > > >>>>>
> > > >>>>>  - I added reference images [3] of all tests to compare with the
> > > >>>>> results that the original code delivered.
> > > >>>>>
> > > >>>>>  - All tests are running using the new backend code and
> pixel-diffs
> > > >>>>> [4] of the produced PNGs show that they render exactly the same.
> > > >>>>>
> > > >>>>>  - I ran into the issue that the ToRenderable class was
> complicated
> > > >>>>> to abstract. My abstraction involved a associated type with two
> parameters
> > > >>>>> that are in relation to each other [5,6]. After talking with Tim
> I removed
> > > >>>>> the ToRenderable code completely and instead just exported
> specific
> > > >>>>> functions for all types directly. This also made the examples
> easier to
> > > >>>>> adjust, since the new ToRenderable class made type annotations
> necessary
> > > >>>>> everywhere, which, in my point of view, defeats the purpose of
> the
> > > >>>>> toRenderable function. It was easier just calling the specific
> function
> > > >>>>> directly. I think the change of API is acceptable, since the
> generalised
> > > >>>>> backend lets type parameters popup everywhere anyway.
> > > >>>>>
> > > >>>>>  The next steps:
> > > >>>>>
> > > >>>>>  - Tim suggested this simplified API instead of the rather
> extensive
> > > >>>>> [0] version used right now: http://hpaste.org/89758 . I will
> work on
> > > >>>>> trimming down the current API and providing all complex
> functions in terms
> > > >>>>> of the new API.
> > > >>>>> - The only downside I see is the Matrix type which (I assume)
> comes
> > > >>>>> from Cairo.Matrix [7]. I would just give a naive implementation
> that
> > > >>>>> contains 6 double values for the affine transformations and
> provide a
> > > >>>>> similar custom API.
> > > >>>>> - I will also try to provide a small EDSL for writing paths to
> make
> > > >>>>> that easier (I guess some short combinators and a monoid
> instance will do
> > > >>>>> fine).
> > > >>>>>
> > > >>>>>  Jan
> > > >>>>>
> > > >>>>>  [0]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/blob/backend-experiment/chart/Graphics/Rendering/Chart/Types.hs#L85
> > > >>>>> [1]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/blob/backend-experiment/chart/Graphics/Rendering/Chart/Backend/Cairo.hs#L80
> > > >>>>> [2]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/tree/ad715c4d216e8fcb494f9919d4fb5459ce7d85c2
> > > >>>>> [3]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/tree/backend-experiment/chart/tests-reference
> > > >>>>>  [4]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/blob/backend-experiment/chart/gen-diffs-png.sh
> > > >>>>>  [5]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/blob/backend-experiment/chart/Graphics/Rendering/Chart/Renderable.hs#L77
> > > >>>>> [6]:
> > > >>>>>
> https://github.com/jbracker/haskell-chart/blob/backend-experiment/chart/Graphics/Rendering/Chart/Layout.hs#L163
> > > >>>>> [7]:
> > > >>>>>
> http://hackage.haskell.org/packages/archive/cairo/0.12.4/doc/html/Graphics-Rendering-Cairo-Matrix.html
> > > >>>>>
> > > >>>>>
> > > >>>>> 2013/6/11 Brent Yorgey <byorgey at seas.upenn.edu>
> > > >>>>>
> > > >>>>>> Hi Jan and all,
> > > >>>>>>
> > > >>>>>> Looks like some great progress!  I'm excited. =) Just a couple
> > > >>>>>> thoughts: one, let me know if you want help staring at the
> funny type
> > > >>>>>> errors with Legend and whatnot.  I'm not familiar with the
> Chart code
> > > >>>>>> but perhaps I can help figure out a good solution for the
> abstraction.
> > > >>>>>>
> > > >>>>>> My other general comment is that I know you and Tim have talked
> a bit
> > > >>>>>> about the problems with having font stuff in IO whereas
> diagrams is
> > > >>>>>> pure.  However, from my point of view it wouldn't be that big
> of a
> > > >>>>>> deal if Chart produced an IO Diagram rather than just a Diagram.
> > > >>>>>> Maybe I haven't thought about it sufficiently but it seems like
> this
> > > >>>>>> would be an easy solution to the problem of needing IO.  I'm
> happy to
> > > >>>>>> talk about it in more detail if you want, and if there are ways
> that
> > > >>>>>> the diagrams API could change to make any of this easier I'm
> happy to
> > > >>>>>> discuss that as well. I'm in the middle of some big refactoring
> anyway
> > > >>>>>> (though don't worry, I don't think it will affect your work on
> porting
> > > >>>>>> Chart very much).
> > > >>>>>>
> > > >>>>>> -Brent
> > > >>>>>>
> > > >>>>>> On Mon, Jun 10, 2013 at 05:24:34PM +0200, Jan Bracker wrote:
> > > >>>>>> > Hi,
> > > >>>>>> >
> > > >>>>>> > Andy: The goal is to abstract Charts from Cairo so we can
> plug in
> > > >>>>>> another
> > > >>>>>> > backend (target is Diagrams). And by that we would also be
> able to
> > > >>>>>> use
> > > >>>>>> > Sunroof through diagrams. Of course in the end it should also
> be
> > > >>>>>> possible
> > > >>>>>> > to implement a Sunroof backend on its own.
> > > >>>>>> >
> > > >>>>>> > Tim:
> > > >>>>>> >
> > > >>>>>> >  > Rather than have the CRender monad take an extra
> parameter, I
> > > >>>>>> guess one
> > > >>>>>> > > could just have a separate data type for each backend (ie
> > > >>>>>> CRenderCairo and
> > > >>>>>> > > CRenderDiagrams) and have the drawing code abstracted over a
> > > >>>>>> typeclass
> > > >>>>>> > > implemented by both. Not sure if this would be better...
> > > >>>>>> > >
> > > >>>>>> >
> > > >>>>>> >  I tried your approach in a new branch:
> > > >>>>>> >
> https://github.com/jbracker/haskell-chart/tree/backend-experiment
> > > >>>>>> >
> > > >>>>>> > It seems to be working quite well. So I started generalizing
> > > >>>>>> everything
> > > >>>>>> > outside of the cairo module to use a general ChartBackend m
> instead
> > > >>>>>> of a
> > > >>>>>> > CRender to draw everything. There are a few spots that are
> giving
> > > >>>>>> me a hard
> > > >>>>>> > time:
> > > >>>>>> >
> > > >>>>>> > Renderable was implemented in terms of CRender. So I added
> another
> > > >>>>>> type
> > > >>>>>> > parameter and that worked fine until I hit Legend. There I
> also
> > > >>>>>> added a
> > > >>>>>> > type parameter. But that blew up the ToRenderable instance.
> So I
> > > >>>>>> had to
> > > >>>>>> > insert a associated type to relate types to each other. After
> doing
> > > >>>>>> so I
> > > >>>>>> > was not able to fix whatever went wrong in Plot.Pie. The
> > > >>>>>> 'ToRenderable
> > > >>>>>> > PieLayout' instance gives me this error:
> > > >>>>>> >
> > > >>>>>> > Graphics/Rendering/Chart/Plot/Pie.hs:121:62:
> > > >>>>>> >     Could not deduce (RenderableT m a0 ~ PieChart)
> > > >>>>>> >     from the context (ChartBackend m)
> > > >>>>>> >       bound by the type signature for
> > > >>>>>> >                  toRenderable :: ChartBackend m =>
> > > >>>>>> >                                  RenderableT m PieLayout ->
> > > >>>>>> Renderable m ()
> > > >>>>>> >       at Graphics/Rendering/Chart/Plot/Pie.hs:(117,5)-(125,29)
> > > >>>>>> >     The type variable `a0' is ambiguous
> > > >>>>>> >     Possible fix: add a type signature that fixes these type
> > > >>>>>> variable(s)
> > > >>>>>> >     In the return type of a call of `pie_plot_'
> > > >>>>>> >     In the second argument of `($)', namely `pie_plot_ p'
> > > >>>>>> >     In the second argument of `addMargins', namely
> > > >>>>>> >       `(toRenderable $ pie_plot_ p)'
> > > >>>>>> >
> > > >>>>>> > I think I know what is going wrong, but I have no idea how to
> > > >>>>>> specify the
> > > >>>>>> > instance it should use there. Maybe I am just to tired to see
> the
> > > >>>>>> solution.
> > > >>>>>> >
> > > >>>>>> > Right now I am trying to make things work without extra type
> > > >>>>>> parameters,
> > > >>>>>> > though the definitions that are based on CRender are giving
> me a
> > > >>>>>> hard time,
> > > >>>>>> > because then I end up with rank N types.
> > > >>>>>> >
> > > >>>>>>   > --
> > > >>>>>> > You received this message because you are subscribed to the
> Google
> > > >>>>>> Groups "diagrams-discuss" group.
> > > >>>>>> > To unsubscribe from this group and stop receiving emails from
> it,
> > > >>>>>> send an email to diagrams-discuss+unsubscribe at googlegroups.com.
> > > >>>>>> > For more options, visit
> https://groups.google.com/groups/opt_out.
> > > >>>>>> >
> > > >>>>>> >
> > > >>>>>>
> > > >>>>>
> > > >>>>>
> > > >>>>
> > > >>>>
> > > >>>
> > > >>
> > > >
> >
> > --
> > You received this message because you are subscribed to the Google
> Groups "diagrams-discuss" group.
> > To unsubscribe from this group and stop receiving emails from it, send
> an email to diagrams-discuss+unsubscribe at googlegroups.com.
> > For more options, visit https://groups.google.com/groups/opt_out.
> >
> >
>
> --
> You received this message because you are subscribed to the Google Groups
> "diagrams-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to diagrams-discuss+unsubscribe at googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://projects.haskell.org/pipermail/chart/attachments/20130710/947affc5/attachment-0001.htm>


More information about the Chart mailing list