diff options
-rwxr-xr-x | blog/dune | 4 | ||||
-rwxr-xr-x | blog/sidebar.ml | 54 | ||||
-rwxr-xr-x | dune | 4 | ||||
-rwxr-xr-x | elements/dune (renamed from events/dune) | 2 | ||||
-rwxr-xr-x | elements/input.ml | 20 | ||||
-rwxr-xr-x | elements/timer.ml (renamed from events/timer.ml) | 0 | ||||
-rwxr-xr-x | elements/timer.mli (renamed from events/timer.mli) | 0 | ||||
-rwxr-xr-x | layer/svg.ml | 68 | ||||
-rwxr-xr-x | path/fillPrinter.ml | 121 | ||||
-rwxr-xr-x | path/wireFramePrinter.ml | 132 | ||||
-rwxr-xr-x | path/wireFramePrinter.mli | 33 | ||||
-rwxr-xr-x | ppx_hash/dune | 6 | ||||
-rwxr-xr-x | ppx_hash/ppx_hash.ml | 32 | ||||
-rwxr-xr-x | script.ml | 93 | ||||
-rwxr-xr-x | shapes/matrix/EltsI.ml (renamed from matrix/EltsI.ml) | 0 | ||||
-rwxr-xr-x | shapes/matrix/Helpers.ml (renamed from matrix/Helpers.ml) | 0 | ||||
-rwxr-xr-x | shapes/matrix/Matrix.ml (renamed from matrix/Matrix.ml) | 0 | ||||
-rwxr-xr-x | shapes/matrix/MatrixI.ml (renamed from matrix/MatrixI.ml) | 0 | ||||
-rwxr-xr-x | shapes/matrix/Order.ml (renamed from matrix/Order.ml) | 0 | ||||
-rwxr-xr-x | shapes/matrix/dune (renamed from matrix/dune) | 0 |
20 files changed, 367 insertions, 202 deletions
@@ -3,6 +3,6 @@ (libraries brr brr.note - js_of_ocaml-tyxml) - (preprocess (pps tyxml-ppx)) + elements + ) ) diff --git a/blog/sidebar.ml b/blog/sidebar.ml index ed4b856..83afb13 100755 --- a/blog/sidebar.ml +++ b/blog/sidebar.ml @@ -24,21 +24,6 @@ let rec clean clean el ) -(** Create a slider element, and the event on change *) -let slider ~at = - let slider = - El.input ~at () in - - let event = - Evr.on_el - Ev.input - (fun _ -> - let raw_value = El.prop El.Prop.value slider in - Jstr.to_int raw_value) - slider - in - slider, event - let click_event el = Evr.on_el Ev.click @@ -51,7 +36,7 @@ let show_value = function El.txt (Jstr.of_int input) let add_button - : El.t -> unit E.t + : El.t -> unit E.t * unit E.t = fun element -> let open El in @@ -73,10 +58,11 @@ let add_button ; class' (Jstr.v "fa-download") ] [] ; txt' "Download"] in + let export_event = click_event export in let nib_size, value = - slider + Elements.Input.slider ~at:At.[ type' (Jstr.v "range") ; v (Jstr.v "min") (Jstr.v "0") ; v (Jstr.v "max") (Jstr.v "50") @@ -84,30 +70,30 @@ let add_button ] in let width = El.div [] in - Elr.set_children + Elr.def_children width - ~on:(value - |> E.map (fun v -> - [ txt' "Width : " - ; show_value v ] - ) - ); + (value + |> S.map (fun v -> + [ txt' "Width : " + ; show_value v ] + ) + ); let input_angle, angle_event = - slider + Elements.Input.slider ~at:At.[ type' (Jstr.v "range") ; v (Jstr.v "min") (Jstr.v "0") ; v (Jstr.v "max") (Jstr.v "90")] in let angle = El.div [] in - Elr.set_children + Elr.def_children angle - ~on:(angle_event - |> E.map (fun v -> - [ txt' "Angle : " - ; show_value v - ; txt' "°" ] - ) - ); + (angle_event + |> S.map (fun v -> + [ txt' "Angle : " + ; show_value v + ; txt' "°" ] + ) + ); let click = Evr.on_el Ev.click Evr.unit delete in let _ = click in @@ -128,4 +114,4 @@ let add_button ] in - delete_event + delete_event, export_event @@ -11,12 +11,12 @@ worker shapes tools - events + elements blog path ) (modes js) - (preprocess (pps js_of_ocaml-ppx)) + (preprocess (pps ppx_hash)) (link_flags (:standard -no-check-prims)) ) diff --git a/events/dune b/elements/dune index 68e2dd2..755bd05 100755 --- a/events/dune +++ b/elements/dune @@ -1,5 +1,5 @@ (library - (name events) + (name elements) (libraries brr brr.note diff --git a/elements/input.ml b/elements/input.ml new file mode 100755 index 0000000..790b15d --- /dev/null +++ b/elements/input.ml @@ -0,0 +1,20 @@ +open Brr +open Brr_note +open Note + +(** Create a slider element, and a signal with the value *) +let slider ~at = + let slider = + El.input ~at () in + + let event = + Evr.on_el + Ev.input (fun _ -> + let raw_value = El.prop El.Prop.value slider in + Jstr.to_int raw_value) + slider + |> S.hold (Jstr.to_int (El.prop El.Prop.value slider)) + in + slider, event + + diff --git a/events/timer.ml b/elements/timer.ml index 0a75e12..0a75e12 100755 --- a/events/timer.ml +++ b/elements/timer.ml diff --git a/events/timer.mli b/elements/timer.mli index 0509ad0..0509ad0 100755 --- a/events/timer.mli +++ b/elements/timer.mli diff --git a/layer/svg.ml b/layer/svg.ml new file mode 100755 index 0000000..f174acc --- /dev/null +++ b/layer/svg.ml @@ -0,0 +1,68 @@ +(** SVG representation *) + +open Brr + +module Path = Brr_canvas.C2d.Path +module V2 = Gg.V2 + + +let svg : El.cons + = fun ?d ?at childs -> + El.v ?d ?at (Jstr.v "svg") childs + +let path: El.cons + = fun ?d ?at childs -> + El.v ?d ?at (Jstr.v "path") childs + +type 'a t = Jstr.t + +let create + : unit -> 'a t + = fun () -> Jstr.empty + +(* Start a new path. *) +let move_to + : Gg.v2 -> 'a t -> 'a t + = fun point path -> + let x, y = V2.to_tuple point in + + Jstr.append path @@ + Jstr.concat ~sep:(Jstr.v " ") + [ Jstr.v " M" + ; Jstr.of_float x + ; Jstr.of_float y ] + + +let line_to + : Gg.v2 -> 'a t -> 'a t + = fun point path -> + let x, y = V2.to_tuple point in + Jstr.append path @@ + Jstr.concat ~sep:(Jstr.v " ") + [ (Jstr.v " L") + ; (Jstr.of_float x) + ; (Jstr.of_float y) ] + +let quadratic_to + : Gg.v2 -> Gg.v2 -> Gg.v2 -> 'a t -> 'a t + = fun ctrl0 ctrl1 p1 path -> + let cx, cy = V2.to_tuple ctrl0 + and cx', cy' = V2.to_tuple ctrl1 + and x, y = V2.to_tuple p1 in + Jstr.append path @@ + Jstr.concat ~sep:(Jstr.v " ") + [ (Jstr.v " C") + ; (Jstr.of_float cx) + ; (Jstr.of_float cy) + ; (Jstr.v ",") + ; (Jstr.of_float cx') + ; (Jstr.of_float cy') + ; (Jstr.v ",") + ; (Jstr.of_float x) + ; (Jstr.of_float y) ] + +let close + : 'a t -> 'a t + = fun path -> + Jstr.append path (Jstr.v " Z") + diff --git a/path/fillPrinter.ml b/path/fillPrinter.ml index d95030c..b506f9b 100755 --- a/path/fillPrinter.ml +++ b/path/fillPrinter.ml @@ -1,71 +1,72 @@ -module Repr = Layer.CanvaPrinter +module Make(Repr: Layer.Repr.PRINTER) = struct -type t = Point.t + type t = Point.t -type 'a repr = - { path: ('a Repr.t) - ; close : 'a Repr.t -> unit - } - -let create_path - : 'b -> 'a repr - = fun f -> - { close = f - ; path = Repr.create () + type 'a repr = + { path: ('a Repr.t) + ; close : 'a Repr.t -> unit } -(* Start a new path. *) -let start - : Point.t -> 'a repr -> 'a repr - = fun t {close ; path } -> - let path = Repr.move_to (Point.get_coord t) path in - { close - ; path - } + let create_path + : 'b -> 'a repr + = fun f -> + { close = f + ; path = Repr.create () + } + + (* Start a new path. *) + let start + : Point.t -> 'a repr -> 'a repr + = fun t {close ; path } -> + let path = Repr.move_to (Point.get_coord t) path in + { close + ; path + } -let line_to - : Point.t -> Point.t -> 'a repr -> 'a repr - = fun p0 p1 t -> - let path = - Repr.move_to (Point.get_coord p1) t.path - |> Repr.line_to (Point.get_coord' p1) - |> Repr.line_to (Point.get_coord' p0) - |> Repr.line_to (Point.get_coord p0) - |> Repr.line_to (Point.get_coord p1) - |> Repr.close in - t.close path; - { t with path} + let line_to + : Point.t -> Point.t -> 'a repr -> 'a repr + = fun p0 p1 t -> + let path = + Repr.move_to (Point.get_coord p1) t.path + |> Repr.line_to (Point.get_coord' p1) + |> Repr.line_to (Point.get_coord' p0) + |> Repr.line_to (Point.get_coord p0) + |> Repr.line_to (Point.get_coord p1) + |> Repr.close in + t.close path; + { t with path} -let quadratic_to - : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr - = fun p0 ctrl0 ctrl1 p1 t -> + let quadratic_to + : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr + = fun p0 ctrl0 ctrl1 p1 t -> - let ctrl0' = Point.copy p1 ctrl0 - and ctrl1' = Point.copy p1 ctrl1 in + let ctrl0' = Point.copy p1 ctrl0 + and ctrl1' = Point.copy p1 ctrl1 in - let path = - Repr.move_to (Point.get_coord p1) t.path - |> Repr.line_to (Point.get_coord' p1) - |> Repr.quadratic_to - (Point.get_coord' ctrl1') - (Point.get_coord' ctrl0') - (Point.get_coord' p0) - |> Repr.line_to (Point.get_coord p0) - |> Repr.quadratic_to - (Point.get_coord ctrl0') - (Point.get_coord ctrl1') - (Point.get_coord p1) - |> Repr.close in - t.close path; - { t with path} + let path = + Repr.move_to (Point.get_coord p1) t.path + |> Repr.line_to (Point.get_coord' p1) + |> Repr.quadratic_to + (Point.get_coord' ctrl1') + (Point.get_coord' ctrl0') + (Point.get_coord' p0) + |> Repr.line_to (Point.get_coord p0) + |> Repr.quadratic_to + (Point.get_coord ctrl0') + (Point.get_coord ctrl1') + (Point.get_coord p1) + |> Repr.close in + t.close path; + { t with path} -let stop - : 'a repr -> 'a repr - = fun t -> - t + let stop + : 'a repr -> 'a repr + = fun t -> + t -let get - : 'a repr -> 'a Repr.t - = fun t -> - t.path + let get + : 'a repr -> 'a Repr.t + = fun t -> + t.path +end diff --git a/path/wireFramePrinter.ml b/path/wireFramePrinter.ml index 13d90ad..47eb9d4 100755 --- a/path/wireFramePrinter.ml +++ b/path/wireFramePrinter.ml @@ -1,78 +1,78 @@ -module Repr = Layer.CanvaPrinter +module Make(Repr: Layer.Repr.PRINTER) = struct + type t = Point.t -type t = Point.t - -type 'a repr = - { back: ('a Repr.t -> 'a Repr.t) - ; path: ('a Repr.t) - ; last_point : Point.t option - } - -let create_path - : 'b -> 'a repr - = fun _ -> - { back = Repr.close - ; path = Repr.create () - ; last_point = None + type 'a repr = + { back: ('a Repr.t -> 'a Repr.t) + ; path: ('a Repr.t) + ; last_point : Point.t option } -(* Start a new path. *) -let start - : Point.t -> 'a repr -> 'a repr - = fun t {back; path; _} -> - let path = Repr.move_to (Point.get_coord t) path in - let line' = Repr.line_to (Point.get_coord' t) in - { back = (fun p -> back @@ line' p) - ; path - ; last_point = Some t - } + let create_path + : 'b -> 'a repr + = fun _ -> + { back = Repr.close + ; path = Repr.create () + ; last_point = None + } -let line_to - : Point.t -> Point.t -> 'a repr -> 'a repr - = fun _ t {back; path; _} -> - let line' = Repr.line_to (Point.get_coord' t) in - { back = (fun t -> back @@ line' t) - ; path = Repr.line_to (Point.get_coord t) path - ; last_point = Some t - } + (* Start a new path. *) + let start + : Point.t -> 'a repr -> 'a repr + = fun t {back; path; _} -> + let path = Repr.move_to (Point.get_coord t) path in + let line' = Repr.line_to (Point.get_coord' t) in + { back = (fun p -> back @@ line' p) + ; path + ; last_point = Some t + } -let quadratic_to - : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr - = fun p0 ctrl0 ctrl1 p1 t -> + let line_to + : Point.t -> Point.t -> 'a repr -> 'a repr + = fun _ t {back; path; _} -> + let line' = Repr.line_to (Point.get_coord' t) in + { back = (fun t -> back @@ line' t) + ; path = Repr.line_to (Point.get_coord t) path + ; last_point = Some t + } - let ctrl0' = Point.copy p1 ctrl0 - and ctrl1' = Point.copy p1 ctrl1 in + let quadratic_to + : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr + = fun p0 ctrl0 ctrl1 p1 t -> - let line' path = - Repr.quadratic_to - (Point.get_coord' @@ ctrl1') - (Point.get_coord' ctrl0') - (Point.get_coord' p0) path in + let ctrl0' = Point.copy p1 ctrl0 + and ctrl1' = Point.copy p1 ctrl1 in - let path = Repr.quadratic_to - (Point.get_coord ctrl0') - (Point.get_coord ctrl1') - (Point.get_coord p1) - t.path in - { back = (fun p -> t.back @@ line' p) - ; path - ; last_point = Some p1 - } + let line' path = + Repr.quadratic_to + (Point.get_coord' @@ ctrl1') + (Point.get_coord' ctrl0') + (Point.get_coord' p0) path in + + let path = Repr.quadratic_to + (Point.get_coord ctrl0') + (Point.get_coord ctrl1') + (Point.get_coord p1) + t.path in + { back = (fun p -> t.back @@ line' p) + ; path + ; last_point = Some p1 + } -let stop - : 'a repr -> 'a repr - = fun {back; path; last_point} -> + let stop + : 'a repr -> 'a repr + = fun {back; path; last_point} -> - let path = - match last_point with - | Some point -> Repr.line_to (Point.get_coord' point) path - | None -> path in + let path = + match last_point with + | Some point -> Repr.line_to (Point.get_coord' point) path + | None -> path in - { back = (fun x -> x) - ; path = back path - ; last_point = None } + { back = (fun x -> x) + ; path = back path + ; last_point = None } -let get - : 'a repr -> 'a Repr.t - = fun {back; path; _} -> - back path + let get + : 'a repr -> 'a Repr.t + = fun {back; path; _} -> + back path +end diff --git a/path/wireFramePrinter.mli b/path/wireFramePrinter.mli index c6b7a98..d6f346e 100755 --- a/path/wireFramePrinter.mli +++ b/path/wireFramePrinter.mli @@ -1,23 +1,26 @@ -type 'a repr +module Make(Repr:Layer.Repr.PRINTER): sig -type t = Point.t + type 'a repr -val create_path - : 'b -> 'a repr + type t = Point.t -(* Start a new path. *) -val start - : Point.t -> 'a repr -> 'a repr + val create_path + : 'b -> 'a repr -val line_to - : Point.t -> Point.t -> 'a repr -> 'a repr + (* Start a new path. *) + val start + : Point.t -> 'a repr -> 'a repr -val quadratic_to - : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr + val line_to + : Point.t -> Point.t -> 'a repr -> 'a repr -val stop - : 'a repr -> 'a repr + val quadratic_to + : Point.t -> Gg.v2 -> Gg.v2 -> Point.t -> 'a repr -> 'a repr -val get - : 'a repr -> 'a Layer.CanvaPrinter.t + val stop + : 'a repr -> 'a repr + val get + : 'a repr -> 'a Repr.t + +end diff --git a/ppx_hash/dune b/ppx_hash/dune new file mode 100755 index 0000000..7cb4bc8 --- /dev/null +++ b/ppx_hash/dune @@ -0,0 +1,6 @@ +(library + (name ppx_hash) + (kind ppx_deriver) + (libraries ppxlib ) + (preprocess (pps ppxlib.metaquot)) + ) diff --git a/ppx_hash/ppx_hash.ml b/ppx_hash/ppx_hash.ml new file mode 100755 index 0000000..59584d5 --- /dev/null +++ b/ppx_hash/ppx_hash.ml @@ -0,0 +1,32 @@ +open Ppxlib + +(** + + This is a simple ppx which evaluate hash for string at compilation time. + + [%static_hash "deadbeef"] is equivalent to [Hashtbl.hash "deadbeef"] + + the ppx only evaluate strings. +*) + +let name = "static_hash" + +let expand ~loc ~path:_ (value : string) = + let h = Hashtbl.hash value in + Ast_builder.Default.eint ~loc h + +let extension = + Extension.declare + name + Extension.Context.expression + Ast_pattern.(single_expr_payload (estring __)) + expand + + + +let rule = Ppxlib.Context_free.Rule.extension extension + +let () = + Driver.register_transformation + ~rules:[rule] + name @@ -2,21 +2,24 @@ open StdLabels open Note open Brr -module Timer = Events.Timer +module Path_Builder = Path.Builder.Make(Path.Point) -module Repr = Path.FillPrinter +module CanvaRepr = Path.FillPrinter.Make(Layer.CanvaPrinter) +module SVGRepr = Path.WireFramePrinter.Make(Layer.Svg) +module Path_Printer = Path_Builder.Draw(CanvaRepr) +module Fixed_Printer = Path_Builder.DrawFixed(CanvaRepr) -module Path_Builder = Path.Builder.Make(Path.Point) -module Path_Printer = Path_Builder.Draw(Repr) -module Fixed_Printer = Path_Builder.DrawFixed(Repr) +module SVG_Fixed_Printer = Path_Builder.DrawFixed(SVGRepr) + +let expected_host = [%static_hash ""] type mode = | Edit | Selection of Path_Builder.fixedPath | Out -let timer, tick = Timer.create () +let timer, tick = Elements.Timer.create () type current = Path_Builder.t @@ -37,7 +40,9 @@ type canva_events = ] type button_events = - [ `Delete ] + [ `Delete + | `Export + ] type events = [ canva_events @@ -151,7 +156,7 @@ let do_action (* Click anywhere while in Out mode, we switch in edition *) | `Click _, Out -> - Timer.start timer 0.3; + Elements.Timer.start timer 0.3; { state with mode = Edit } (* Click anywhere while in selection mode, we either select another path, @@ -164,15 +169,15 @@ let do_action | Some selected -> (* Start the timer in order to handle the mouse moves *) - Timer.start timer 0.3; + Elements.Timer.start timer 0.3; { state with mode = (Selection selected)} end | `Out point, Edit -> - Timer.stop timer; + Elements.Timer.stop timer; begin match Path_Builder.peek2 state.current with - (** If there is at last two points selected, handle this as a curve + (* If there is at last two points selected, handle this as a curve creation *) | Some _ -> let current, fixed_path = insert_or_replace point state.current in @@ -183,7 +188,7 @@ let do_action { mode = Out ; paths; current } - (** Else, check if there is a curve undre the cursor, and remove it *) + (* Else, check if there is a curve undre the cursor, and remove it *) | None -> let current = Path_Builder.empty in begin match check_selection point state.paths with @@ -202,6 +207,47 @@ let do_action let id = Path_Builder.id s in let paths = List.filter state.paths ~f:(fun p -> Path_Builder.id p != id) in { state with paths ; mode = Out} + + + | `Export, _ -> + + let my_host = Uri.host @@ Window.location @@ G.window in + + if (Hashtbl.hash my_host) = expected_host then ( + (* Convert the path into an sVG element *) + let svg = Layer.Svg.svg + ~at:Brr.At.[ + v (Jstr.v "xmlns") (Jstr.v "http://www.w3.org/2000/svg") + ; v (Jstr.v "xmlns:xlink") (Jstr.v "http://www.w3.org/1999/xlink") ] + (List.map state.paths + ~f:(fun path -> + let repr = SVGRepr.create_path (fun _ -> ()) in + let path = SVGRepr.get @@ SVG_Fixed_Printer.draw path repr in + + Layer.Svg.path + ~at:Brr.At.[ + v (Jstr.v "fill") (Jstr.v "#000000") + ; v (Jstr.v "stroke") (Jstr.v "#000000") + ; v (Jstr.v "d") path ] + [] + )) in + let content = El.prop (El.Prop.jstr @@ Jstr.v "outerHTML") svg in + + let btoa = Jv.get Jv.global "btoa" in + let base64data = Jv.apply btoa + [| Jv.of_jstr content |] in + + (* Create the link to download the the element, and simulate a click on it *) + let a = El.a + ~at:At.[ + href Jstr.( (v "data:image/svg+xml;base64,") + (Jv.Id.of_jv base64data)) + ; v (Jstr.v "download") (Jstr.v "out.svg") + ] + [] in + El.click a + ); + state + | _ -> state let backgroundColor = Jstr.v "#2e3440" @@ -247,18 +293,18 @@ let on_change canva mouse_position state = end in - let path = Repr.get + let path = CanvaRepr.get @@ Path_Printer.draw current - (Repr.create_path (fun p -> fill context p)) in + (CanvaRepr.create_path (fun p -> fill context p)) in stroke context path; List.iter paths ~f:(fun path -> - let path = Repr.get + let path = CanvaRepr.get @@ Fixed_Printer.draw path - (Repr.create_path (fun p -> fill context p)) in + (CanvaRepr.create_path (fun p -> fill context p)) in stroke context path; ); @@ -268,10 +314,10 @@ let on_change canva mouse_position state = | Selection path -> set_fill_style context (color nord8); set_stroke_style context (color nord8); - let path = Repr.get + let path = CanvaRepr.get @@ Fixed_Printer.draw path - (Repr.create_path (fun p -> fill context p)) in + (CanvaRepr.create_path (fun p -> fill context p)) in stroke context path; | _ -> () in () @@ -285,7 +331,7 @@ let page_main id = ; mode = Out } in - let delete_event' = + let delete_event', export_event' = begin match Blog.Sidebar.get () with | None -> Jv.throw (Jstr.v "No sidebar") @@ -295,7 +341,8 @@ let page_main id = let event = Blog.Sidebar.add_button el in event end in - let delete_event = E.map (fun () -> `Delete) delete_event' in + let delete_event = E.map (fun () -> `Delete) delete_event' + and export_event = E.map (fun () -> `Export) export_event' in (*begin match Document.find_el_by_id G.document id with*) @@ -321,7 +368,7 @@ let page_main id = (* The first evaluation is the state. Which is the result of all the successives events to the initial state *) let state = - E.select [canva_events; tick_event; delete_event] + E.select [canva_events; tick_event; delete_event; export_event] |> E.map do_action |> Note.S.accum init in @@ -347,10 +394,12 @@ let page_main id = let () = if Brr_webworkers.Worker.ami () then () - else + else ( + let open Jv in let drawer = obj [| "run", (repr page_main) |] in set global "drawer" drawer + ) diff --git a/matrix/EltsI.ml b/shapes/matrix/EltsI.ml index fcfdb50..fcfdb50 100755 --- a/matrix/EltsI.ml +++ b/shapes/matrix/EltsI.ml diff --git a/matrix/Helpers.ml b/shapes/matrix/Helpers.ml index 6980052..6980052 100755 --- a/matrix/Helpers.ml +++ b/shapes/matrix/Helpers.ml diff --git a/matrix/Matrix.ml b/shapes/matrix/Matrix.ml index 7f1d54b..7f1d54b 100755 --- a/matrix/Matrix.ml +++ b/shapes/matrix/Matrix.ml diff --git a/matrix/MatrixI.ml b/shapes/matrix/MatrixI.ml index fbc4e21..fbc4e21 100755 --- a/matrix/MatrixI.ml +++ b/shapes/matrix/MatrixI.ml diff --git a/matrix/Order.ml b/shapes/matrix/Order.ml index 5f2aa22..5f2aa22 100755 --- a/matrix/Order.ml +++ b/shapes/matrix/Order.ml diff --git a/matrix/dune b/shapes/matrix/dune index 1c0cab6..1c0cab6 100755 --- a/matrix/dune +++ b/shapes/matrix/dune |