diff --git a/examples/circle_packing.ml b/examples/circle_packing.ml index e94d733..4b20e27 100644 --- a/examples/circle_packing.ml +++ b/examples/circle_packing.ml @@ -94,9 +94,7 @@ let () = let circles = List.map (fun ((x, y), radius) -> - circle - ~c:{x; y} - (int_of_float radius) + circle ~c:{ x; y } (int_of_float radius) |> with_stroke (rand_nth palette)) concentric in diff --git a/lib/color.ml b/lib/color.ml index 18a8caa..bee833c 100644 --- a/lib/color.ml +++ b/lib/color.ml @@ -1,26 +1,10 @@ type color = int * int * int -(** RGB code for black *) let black = (0, 0, 0) - -(** RGB code for white *) let white = (255, 255, 255) - -(** RGB code for red *) let red = (255, 1, 1) - -(** RGB code for green *) let green = (1, 255, 1) - -(** RGB code for blue *) let blue = (1, 1, 255) - -(** RGB code for yellow *) let yellow = (255, 255, 1) - -(** RGBA constant to set transparent background *) let transparent = (0, 0, 0, 0) - -(** Converts RGB color into opaque RGBA color. - For use w/ `Context.background` *) let opaque (r, g, b) = (r, g, b, 255) diff --git a/lib/color.mli b/lib/color.mli index 7ac3165..97f1064 100644 --- a/lib/color.mli +++ b/lib/color.mli @@ -1,3 +1,5 @@ +(** Color handling & color constants *) + type color = int * int * int val black : color diff --git a/lib/context.ml b/lib/context.ml index 33ede8f..d36dcbf 100644 --- a/lib/context.ml +++ b/lib/context.ml @@ -6,7 +6,6 @@ type context = { axes : bool; } -(* Renders context to PNG *) let write ctx filename = Cairo.PNG.write ctx.surface filename; Cairo.Surface.finish ctx.surface @@ -45,9 +44,6 @@ let background color = Cairo.fill ctx | None -> fail () -(** Sets the width of lines for both stroke of shapes and line primitives. - Can be any positive integer, with larger numbers producing thicker lines. - default is 2 *) let set_line_width line_width = match !context with | Some ctx -> Cairo.set_line_width ctx.ctx (float_of_int line_width) diff --git a/lib/context.mli b/lib/context.mli index d9f36a9..5d26941 100644 --- a/lib/context.mli +++ b/lib/context.mli @@ -15,6 +15,9 @@ val resolution : unit -> int * int val set_color : int * int * int -> unit val background : int * int * int * int -> unit val set_line_width : int -> unit + val write : context -> string -> unit +(** Writes the current digital canvas to a PNG file *) + val save : unit -> unit val restore : unit -> unit diff --git a/lib/joy.ml b/lib/joy.ml index b6eb36a..ed6e364 100644 --- a/lib/joy.ml +++ b/lib/joy.ml @@ -1,12 +1,8 @@ -let context = Context.context - type 'a point = 'a Shape.point type shape = Shape.shape type shapes = Shape.shapes type transformation = Transform.transformation - type color = Color.color -(** Three-tuple representing a 24-bit RGB color *) let black = Color.black let white = Color.white @@ -36,9 +32,8 @@ let set_line_width = Context.set_line_width let init ?(background = Color.white) ?(line_width = 2) ?(size = (500, 500)) ?(axes = false) () = - Context.init_context (Color.opaque background) - (float_of_int line_width) - size axes + Context.init_context (Color.opaque background) (float_of_int line_width) size + axes let write ?(filename = "joy.png") () = match !Context.context with diff --git a/lib/joy.mli b/lib/joy.mli index bfd4982..dbd948b 100644 --- a/lib/joy.mli +++ b/lib/joy.mli @@ -1,35 +1,101 @@ type 'a point = 'a Shape.point +(** A point in 2d space + generic but library functions require numeric types *) + type shape = Shape.shape +(** Shape variant type, this is what all shape constructor functions return. + Contains types that are only meant for internal use, you should never need + to construct this type yourself. + *) + type shapes = Shape.shapes +(** A list of {!shape} *) + type transformation = Transform.transformation +(** A function that takes a {!shape} and returns that + {!shape} with an operation applied to at least one field *) + type color = Color.color +(** Represents an RGB color *) val point : int -> int -> float point +(** {!point} constructor function *) + val circle : ?c:float point -> int -> shape +(** {!circle} constructor function *) + val rectangle : ?c:float point -> int -> int -> shape +(** {!rectangle} constructor function *) + val ellipse : ?c:float point -> int -> int -> shape +(** {!ellipse} constructor function *) + val line : ?a:float point -> float point -> shape +(** {!line} constructor function *) + val polygon : float point list -> shape +(** {!polygon} consructor function *) + val complex : shapes -> shape +(** {!complex} constructor function *) + val with_stroke : color -> shape -> shape +(** Creates a new {!shape} with stroke [color] *) + val with_fill : color -> shape -> shape +(** Creates a new {!shape} with fill [color], does not affect {!line} *) + val rotate : int -> transformation +(** Rotates {!shape} by n degrees *) + val translate : int -> int -> transformation +(** Adds {[ { dx; dy } ]} to {!shape}'s position *) + val scale : float -> transformation +(** Multiplies {!shape}'s size by scaling factor *) + val compose : transformation -> transformation -> transformation +(** Composes two {!transformation}, returning a function that executes + both, feeding the result of the first into the second *) + val repeat : int -> transformation -> transformation +(** Iterative transformation - applies {!transformation} to {!shape} n + times, feeding the result into the next iteration *) + val map_stroke : (color -> color) -> shape -> shape +(** Applies f to stroke of {!shape} *) + val map_fill : (color -> color) -> shape -> shape -val context : Context.context option ref +(** Applies f to fill of {!shape}, does not affect {!line} *) + val set_line_width : int -> unit +(** Sets the width of lines for both stroke of shapes and line primitives. + Can be any positive integer, with larger numbers producing thicker lines. + default is 2 *) + val black : color +(** RGB code for black *) + val white : color +(** RGB code for white *) + val red : color +(** RGB code for red *) + val green : color +(** RGB code for green *) + val blue : color +(** RGB code for blue *) + val yellow : color +(** RGB code for yellow *) + val transparent : int * int * int * int +(** RGBA code for a transparent color to use when setting the background color of sketches *) + val opaque : color -> int * int * int * int +(** Takes an RGB color and returns an opaque RGBA color *) val init : ?background:color -> @@ -38,7 +104,14 @@ val init : ?axes:bool -> unit -> unit +(** Initializes drawing context, takes optional arguments to set background color, + line width, and resolution(size) *) val render : shape -> unit + val show : shapes -> unit +(** Renders a list of shapes to canvas *) + val write : ?filename:string -> unit -> unit +(** Writes the current digital canvas to a PNG file, takes a filename + (i.e. "joy.png") as an optional argument *) diff --git a/lib/render.ml b/lib/render.ml index eca4a77..46486b2 100644 --- a/lib/render.ml +++ b/lib/render.ml @@ -17,7 +17,7 @@ let draw_circle ctx ({ c; radius; stroke; fill } : circle) = Option.iter fill_circle fill; Cairo.Path.clear ctx.ctx -let create_control_points ({x; y}, rx, ry) = +let create_control_points ({ x; y }, rx, ry) = let half_height = ry /. 2. in let width_two_thirds = rx *. (2. /. 3.) *. 2. in ( { x; y = y -. half_height }, @@ -74,10 +74,7 @@ let rec partition n ?(step = 0) lst = | [] -> [] | _ -> let taken, _ = take n lst in - if List.length taken = n then - taken - :: - partition n ~step (List.tl lst) + if List.length taken = n then taken :: partition n ~step (List.tl lst) else [] let draw_polygon ctx { vertices = points; stroke; fill } = @@ -113,6 +110,7 @@ let rec render_shape ctx = function let render shape = match !context with Some ctx -> render_shape ctx shape | None -> fail () +(** Renders a list of shapes *) let show shapes = match !context with | Some ctx -> List.iter (render_shape ctx) shapes diff --git a/lib/shape.ml b/lib/shape.ml index ffc347a..e0a01ec 100644 --- a/lib/shape.ml +++ b/lib/shape.ml @@ -1,4 +1,6 @@ type 'a point = { x : 'a; y : 'a } +(** A point in 2d space *) + type color = Color.color type line = { a : float point; b : float point; stroke : color } diff --git a/lib/transform.ml b/lib/transform.ml index 536f936..4dc3eb7 100644 --- a/lib/transform.ml +++ b/lib/transform.ml @@ -96,8 +96,6 @@ let repeat n op shape = let shapes = List.fold_right (fun _ acc -> match_list acc) (range n) [] in complex shapes -(** Takes a function and a shape and returns a new shape with the - function applied to the original's color *) let rec map_stroke f = function | Circle circle' -> Circle { circle' with stroke = Option.map f circle'.stroke }