since import * as IO from 'fp-ts/lib/IO' ; import * as M from 'fp-ts/lib/Monoid' ; import * as O from 'fp-ts/lib/Option' ; import * as RA from 'fp-ts/lib/ReadonlyArray' ; import { flow } from 'fp-ts/lib/function' ; import { pipe } from 'fp-ts/lib/pipeable' ; import * as R from 'fp-ts-contrib/lib/ReaderIO' ; import * as C from './Canvas' ; import { toCss , Color } from './Color' ; import { showFont , Font } from './Font' ; import { Point , Shape } from './Shape' ; const readonlyArrayMonoidDrawing = RA . getMonoid < Drawing > ( ) ; const getFirstMonoidColor = O . getFirstMonoid < Color > ( ) ; const getFirstMonoidNumber = O . getFirstMonoid < number > ( ) ; const getFirstMonoidPoint = O . getFirstMonoid < Point > ( ) ; const traverseReaderIO = RA . readonlyArray . traverse ( R . readerIO ) ; category since export interface Clipped { readonly _tag : 'Clipped' ; /**
     * The shape to use for clipping.
     */ readonly shape : Shape ; /**
     * The drawing to be clipped.
     */ readonly drawing : Drawing ; } category since export interface Fill { readonly _tag : 'Fill' ; /**
     * The filled `Shape`.
     */ readonly shape : Shape ; /**
     * The fill style applied to the `Shape`.
     */ readonly style : FillStyle ; } category since export interface FillStyle { /**
     * The fill color.
     */ readonly color : O . Option < Color > ; } category since export interface Outline { readonly _tag : 'Outline' ; /**
     * The outlined `Shape`.
     */ readonly shape : Shape ; /**
     * The outline style applied to the `Shape`.
     */ readonly style : OutlineStyle ; } category since export interface OutlineStyle { /**
     * The outline color.
     */ readonly color : O . Option < Color > ; /**
     * The outline line width.
     */ readonly lineWidth : O . Option < number > ; } category since export interface Many { readonly _tag : 'Many' ; /**
     * The collection of drawings.
     */ readonly drawings : ReadonlyArray < Drawing > ; } category since export interface Rotate { readonly _tag : 'Rotate' ; /**
     * The angle of rotation.
     */ readonly angle : number ; /**
     * The drawing to be rotated.
     */ readonly drawing : Drawing ; } category since export interface Scale { readonly _tag : 'Scale' ; /**
     * The x-axis scale.
     */ readonly scaleX : number ; /**
     * The y-axis scale.
     */ readonly scaleY : number ; /**
     * The drawing to be scaled.
     */ readonly drawing : Drawing ; } category since export interface Text { readonly _tag : 'Text' ; /**
     * The font style applied to the text.
     */ readonly font : Font ; /**
     * The x-axis coordinate at which to begin drawing the text.
     */ readonly x : number ; /**
     * The y-axis coordinate at which to begin drawing the text.
     */ readonly y : number ; /**
     * The fill style applied to the text.
     */ readonly style : FillStyle ; /**
     * The HTML text string.
     */ readonly text : string ; } category since export interface Translate { readonly _tag : 'Translate' ; /**
     * The x-axis translation.
     */ readonly translateX : number ; /**
     * The y-axis translation.
     */ readonly translateY : number ; /**
     * The drawing to be translated.
     */ readonly drawing : Drawing ; } category since export interface WithShadow { readonly _tag : 'WithShadow' ; /**
     * The shadow to be applied.
     */ readonly shadow : Shadow ; /**
     * The drawing to be shadowed.
     */ readonly drawing : Drawing ; } category since export interface Shadow { /**
     * The shadow color.
     */ readonly color : O . Option < Color > ; /**
     * The shadow blur radius.
     */ readonly blur : O . Option < number > ; /**
     * The shadow offset.
     */ readonly offset : O . Option < Point > ; } category since export type Drawing = Clipped | Fill | Outline | Many | Rotate | Scale | Text | Translate | WithShadow ; category since export const clipped = ( shape , drawing ) => ( { _tag : 'Clipped' , shape , drawing } ) ; category since export const fill = ( shape , style ) => ( { _tag : 'Fill' , shape , style } ) ; category since export const fillStyle = ( c ) => ( { color : O . some ( c ) } ) ; category since export const outline = ( shape , style ) => ( { _tag : 'Outline' , shape , style } ) ; category since export const outlineColor = ( c ) => ( { color : O . some ( c ) , lineWidth : O . none } ) ; category since export const lineWidth = ( w ) => ( { color : O . none , lineWidth : O . some ( w ) } ) ; category since export const many = ( drawings ) => ( { _tag : 'Many' , drawings } ) ; category since export const rotate = ( angle , drawing ) => ( { _tag : 'Rotate' , angle , drawing } ) ; category since export const scale = ( scaleX , scaleY , drawing ) => ( { _tag : 'Scale' , scaleX , scaleY , drawing } ) ; category since export const text = ( font , x , y , style , text ) => ( { _tag : 'Text' , font , x , y , style , text } ) ; category since export const translate = ( translateX , translateY , drawing ) => ( { _tag : 'Translate' , translateX , translateY , drawing } ) ; category since export const withShadow = ( shadow , drawing ) => ( { _tag : 'WithShadow' , shadow , drawing } ) ; category since export const shadowBlur = ( b ) => ( { color : O . none , blur : O . some ( b ) , offset : O . none } ) ; category since export const shadowColor = ( c ) => ( { color : O . some ( c ) , blur : O . none , offset : O . none } ) ; category since export const shadowOffset = ( o ) => ( { color : O . none , blur : O . none , offset : O . some ( o ) } ) ; const applyStyle = ( fa , f ) => pipe ( fa , O . fold ( ( ) => IO . of , f ) ) ; category since export const renderShape = ( shape ) => { switch ( shape . _tag ) { case 'Arc' : return C . arc ( shape ) ; case 'Composite' : return pipe ( traverseReaderIO ( shape . shapes , renderShape ) , R . chain ( ( ) => R . ask ( ) ) ) ; case 'Ellipse' : return C . ellipse ( shape ) ; case 'Path' : return pipe ( shape . points , RA . foldLeft ( ( ) => IO . of , ( head , tail ) => pipe ( C . moveTo ( head ) , R . chain ( ( ) => traverseReaderIO ( tail , C . lineTo ) ) , R . chain ( ( ) => ( shape . closed ? C . closePath : IO . of ) ) ) ) ) ; case 'Rect' : return C . rect ( shape ) ; } } ; category since export const render = ( drawing ) => { const go = ( d ) => { switch ( d . _tag ) { case 'Clipped' : return C . withContext ( pipe ( C . beginPath , R . chain ( ( ) => renderShape ( d . shape ) ) , R . chain ( ( ) => C . clip ( ) ) , R . chain ( ( ) => go ( d . drawing ) ) ) ) ; case 'Fill' : return C . withContext ( pipe ( applyStyle ( d . style . color , flow ( toCss , C . setFillStyle ) ) , R . chain ( ( ) => C . fillPath ( renderShape ( d . shape ) ) ) ) ) ; case 'Many' : return pipe ( traverseReaderIO ( d . drawings , go ) , R . chain ( ( ) => R . ask ( ) ) ) ; case 'Outline' : return C . withContext ( pipe ( applyStyle ( d . style . color , flow ( toCss , C . setStrokeStyle ) ) , R . chain ( ( ) => applyStyle ( d . style . lineWidth , C . setLineWidth ) ) , R . chain ( ( ) => C . strokePath ( renderShape ( d . shape ) ) ) ) ) ; case 'Rotate' : return C . withContext ( pipe ( C . rotate ( d . angle ) , R . chain ( ( ) => go ( d . drawing ) ) ) ) ; case 'Scale' : return C . withContext ( pipe ( C . scale ( d . scaleX , d . scaleY ) , R . chain ( ( ) => go ( d . drawing ) ) ) ) ; case 'Text' : return C . withContext ( pipe ( C . setFont ( showFont . show ( d . font ) ) , R . chain ( ( ) => applyStyle ( d . style . color , flow ( toCss , C . setFillStyle ) ) ) , R . chain ( ( ) => C . fillText ( d . text , d . x , d . y ) ) ) ) ; case 'Translate' : return C . withContext ( pipe ( C . translate ( d . translateX , d . translateY ) , R . chain ( ( ) => go ( d . drawing ) ) ) ) ; case 'WithShadow' : return C . withContext ( pipe ( applyStyle ( d . shadow . color , flow ( toCss , C . setShadowColor ) ) , R . chain ( ( ) => applyStyle ( d . shadow . blur , C . setShadowBlur ) ) , R . chain ( ( ) => applyStyle ( d . shadow . offset , ( o ) => pipe ( C . setShadowOffsetX ( o . x ) , R . chain ( ( ) => C . setShadowOffsetY ( o . y ) ) ) ) ) , R . chain ( ( ) => go ( d . drawing ) ) ) ) ; } } ; return go ( drawing ) ; } ; category since export const monoidFillStyle = M . getStructMonoid < FillStyle > ( { color : getFirstMonoidColor } ) ; example category since export const monoidOutlineStyle = M . getStructMonoid < OutlineStyle > ( { color : getFirstMonoidColor , lineWidth : getFirstMonoidNumber } ) ; category since export const monoidShadow = M . getStructMonoid < Shadow > ( { color : getFirstMonoidColor , blur : getFirstMonoidNumber , offset : getFirstMonoidPoint } ) ; category since export const monoidDrawing = { concat : ( x , y ) => x . _tag === 'Many' && y . _tag === 'Many' ? many ( M . fold ( readonlyArrayMonoidDrawing ) ( [ x . drawings , y . drawings ] ) ) : x . _tag === 'Many' ? many ( M . fold ( readonlyArrayMonoidDrawing ) ( [ x . drawings , [ y ] ] ) ) : y . _tag === 'Many' ? many ( M . fold ( readonlyArrayMonoidDrawing ) ( [ [ x ] , y . drawings ] ) ) : many ( [ x , y ] ) , empty : many ( readonlyArrayMonoidDrawing . empty ) } ;