{-# LANGUAGE DeriveDataTypeable
, ExistentialQuantification
, GeneralizedNewtypeDeriving
#-}------------------------------------------------------------------------------- |-- Module : Diagrams.Attributes-- Copyright : (c) 2011 diagrams-lib team (see LICENSE)-- License : BSD-style (see LICENSE)-- Maintainer : diagrams-discuss@googlegroups.com---- Diagrams may have /attributes/ which affect the way they are-- rendered. This module defines some common attributes; particular-- backends may also define more backend-specific attributes.---- Every attribute type must have a /semigroup/ structure, that is, an-- associative binary operation for combining two attributes into one.-- Unless otherwise noted, all the attributes defined here use the-- 'Last' structure, that is, combining two attributes simply keeps-- the second one and throws away the first. This means that child-- attributes always override parent attributes.-------------------------------------------------------------------------------moduleDiagrams.Attributes(-- * Color-- $colorColor(..),SomeColor(..)-- ** Line color,LineColor,getLineColor,lineColor,lc,lcA-- ** Fill color,FillColor,getFillColor,recommendFillColor,fillColor,fc,fcA-- ** Opacity,Opacity,getOpacity,opacity-- * Lines-- ** Width,LineWidth,getLineWidth,lineWidth,lw-- ** Cap style,LineCap(..),LineCapA,getLineCap,lineCap-- ** Join style,LineJoin(..),LineJoinA,getLineJoin,lineJoin-- ** Dashing,Dashing(..),DashingA,getDashing,dashing)whereimportDiagrams.CoreimportData.ColourimportqualifiedData.Colour.SRGBasRGBimportData.TypeableimportData.Monoid.RecommendimportData.Semigroup-------------------------------------------------------------- Color --------------------------------------------------------------------------------------------------------------- $color-- Diagrams outsources all things color-related to Russell O\'Connor\'s-- very nice colour package-- (<http://hackage.haskell.org/package/colour>). For starters, it-- provides a large collection of standard color names. However, it-- also provides a rich set of combinators for combining and-- manipulating colors; see its documentation for more information.-- | The 'Color' type class encompasses color representations which-- can be used by the Diagrams library. Instances are provided for-- both the 'Data.Colour.Colour' and 'Data.Colour.AlphaColour' types-- from the "Data.Colour" library.classColorcwhere-- | Convert a color to red, green, blue, and alpha channels in the-- range [0,1].colorToRGBA::c->(Double,Double,Double,Double)-- | An existential wrapper for instances of the 'Color' class.dataSomeColor=forallc.Colorc=>SomeColorcderivingTypeable-- | The color with which lines (strokes) are drawn. Note that child-- colors always override parent colors; that is, @'lineColor' c1-- . 'lineColor' c2 $ d@ is equivalent to @'lineColor' c2 $ d@.-- More precisely, the semigroup structure on line color attributes-- is that of 'Last'.newtypeLineColor=LineColor(LastSomeColor)deriving(Typeable,Semigroup)instanceAttributeClassLineColorgetLineColor::LineColor->SomeColorgetLineColor(LineColor(Lastc))=c-- | Set the line (stroke) color. This function is polymorphic in the-- color type (so it can be used with either 'Colour' or-- 'AlphaColour'), but this can sometimes create problems for type-- inference, so the 'lc' and 'lcA' variants are provided with more-- concrete types.lineColor::(Colorc,HasStylea)=>c->a->alineColor=applyAttr.LineColor.Last.SomeColor-- | A synonym for 'lineColor', specialized to @'Colour' Double@-- (i.e. opaque colors).lc::HasStylea=>ColourDouble->a->alc=lineColor-- | A synonym for 'lineColor', specialized to @'AlphaColour' Double@-- (i.e. colors with transparency).lcA::HasStylea=>AlphaColourDouble->a->alcA=lineColor-- | The color with which shapes are filled. Note that child-- colors always override parent colors; that is, @'fillColor' c1-- . 'fillColor' c2 $ d@ is equivalent to @'lineColor' c2 $ d@.-- More precisely, the semigroup structure on fill color attributes-- is that of 'Last'.newtypeFillColor=FillColor(Recommend(LastSomeColor))deriving(Typeable,Semigroup)instanceAttributeClassFillColor-- | Set the fill color. This function is polymorphic in the color-- type (so it can be used with either 'Colour' or 'AlphaColour'),-- but this can sometimes create problems for type inference, so the-- 'fc' and 'fcA' variants are provided with more concrete types.fillColor::(Colorc,HasStylea)=>c->a->afillColor=applyAttr.FillColor.Commit.Last.SomeColor-- | Set a \"recommended\" fill color, to be used only if no explicit-- calls to 'fillColor' (or 'fc', or 'fcA') are used.recommendFillColor::(Colorc,HasStylea)=>c->a->arecommendFillColor=applyAttr.FillColor.Recommend.Last.SomeColorgetFillColor::FillColor->SomeColorgetFillColor(FillColorc)=getLast.getRecommend$c-- | A synonym for 'fillColor', specialized to @'Colour' Double@-- (i.e. opaque colors).fc::HasStylea=>ColourDouble->a->afc=fillColor-- | A synonym for 'fillColor', specialized to @'AlphaColour' Double@-- (i.e. colors with transparency).fcA::HasStylea=>AlphaColourDouble->a->afcA=fillColorinstance(Floatinga,Reala)=>Color(Coloura)wherecolorToRGBAcol=(r,g,b,1)wherec'=RGB.toSRGB.colourConvert$colr=RGB.channelRedc'g=RGB.channelGreenc'b=RGB.channelBluec'instance(Floatinga,Reala)=>Color(AlphaColoura)wherecolorToRGBAcol=(r,g,b,a)wherecol'=alphaColourConvertcola=alphaChannelcol'c'=RGB.toSRGB.alphaToColour$col'r=RGB.channelRedc'g=RGB.channelGreenc'b=RGB.channelBluec'instanceColorSomeColorwherecolorToRGBA(SomeColorc)=colorToRGBAcinstanceColorLineColorwherecolorToRGBA(LineColor(Lastc))=colorToRGBAcinstanceColorFillColorwherecolorToRGBA(FillColorc)=colorToRGBA.getLast.getRecommend$calphaToColour::(Floatinga,Orda,Fractionala)=>AlphaColoura->ColouraalphaToColourac|alphaChannelac==0=ac`over`black|otherwise=darken(recip(alphaChannelac))(ac`over`black)-------------------------------------------------------------- Opacity-- | Although the individual colors in a diagram can have-- transparency, the opacity/transparency of a diagram as a whole-- can be specified with the @Opacity@ attribute. The opacity is a-- value between 1 (completely opaque, the default) and 0-- (completely transparent). Opacity is multiplicative, that is,-- @'opacity' o1 . 'opacity' o2 === 'opacity' (o1 * o2)@. In other-- words, for example, @opacity 0.8@ means \"decrease this diagram's-- opacity to 80% of its previous opacity\".newtypeOpacity=Opacity(ProductDouble)deriving(Typeable,Semigroup)instanceAttributeClassOpacitygetOpacity::Opacity->DoublegetOpacity(Opacity(Productd))=d-- | Multiply the opacity (see 'Opacity') by the given value. For-- example, @opacity 0.8@ means \"decrease this diagram's opacity to-- 80% of its previous opacity\".opacity::HasStylea=>Double->a->aopacity=applyAttr.Opacity.Product-------------------------------------------------------------- Lines and stuff --------------------------------------------------------------------------------------------------- | The width of lines. By default, the line width is measured with-- respect to the /final/ coordinate system of a rendered diagram,-- as opposed to the local coordinate systems in effect at the time-- the line width was set for various subdiagrams. This is so that-- it is easy to combine a variety of shapes (some created by-- scaling) and have them all drawn using a consistent line width.-- However, sometimes it is desirable for scaling to affect line-- width; the 'freeze' operation is provided for this purpose. The-- line width of frozen diagrams is affected by transformations.---- Line widths specified on child nodes always override line widths-- specified at parent nodes.newtypeLineWidth=LineWidth(LastDouble)deriving(Typeable,Semigroup)instanceAttributeClassLineWidthgetLineWidth::LineWidth->DoublegetLineWidth(LineWidth(Lastw))=w-- | Set the line (stroke) width.lineWidth::HasStylea=>Double->a->alineWidth=applyAttr.LineWidth.Last-- | A convenient synonym for 'lineWidth'.lw::HasStylea=>Double->a->alw=lineWidth-- | What sort of shape should be placed at the endpoints of lines?dataLineCap=LineCapButt-- ^ Lines end precisely at their endpoints.|LineCapRound-- ^ Lines are capped with semicircles-- centered on endpoints.|LineCapSquare-- ^ Lines are capped with a squares-- centered on endpoints.deriving(Eq,Show,Typeable)newtypeLineCapA=LineCapA(LastLineCap)deriving(Typeable,Semigroup,Eq)instanceAttributeClassLineCapAgetLineCap::LineCapA->LineCapgetLineCap(LineCapA(Lastc))=c-- | Set the line end cap attribute.lineCap::HasStylea=>LineCap->a->alineCap=applyAttr.LineCapA.Last-- | How should the join points between line segments be drawn?dataLineJoin=LineJoinMiter-- ^ Use a \"miter\" shape (whatever that is).|LineJoinRound-- ^ Use rounded join points.|LineJoinBevel-- ^ Use a \"bevel\" shape (whatever-- that is). Are these...-- carpentry terms?deriving(Eq,Show,Typeable)newtypeLineJoinA=LineJoinA(LastLineJoin)deriving(Typeable,Semigroup,Eq)instanceAttributeClassLineJoinAgetLineJoin::LineJoinA->LineJoingetLineJoin(LineJoinA(Lastj))=j-- | Set the segment join style.lineJoin::HasStylea=>LineJoin->a->alineJoin=applyAttr.LineJoinA.Last-- | Create lines that are dashing... er, dashed.dataDashing=Dashing[Double]Doublederiving(Typeable,Eq)newtypeDashingA=DashingA(LastDashing)deriving(Typeable,Semigroup,Eq)instanceAttributeClassDashingAgetDashing::DashingA->DashinggetDashing(DashingA(Lastd))=d-- | Set the line dashing style.dashing::HasStylea=>[Double]-- ^ A list specifying alternate lengths of on-- and off portions of the stroke. The empty-- list indicates no dashing.->Double-- ^ An offset into the dash pattern at which the-- stroke should start.->a->adashingdsoffs=applyAttr(DashingA(Last(Dashingdsoffs)))