aboutsummaryrefslogtreecommitdiff
path: root/script.ml
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@chimrod.com>2020-12-23 19:11:31 +0100
committerSébastien Dailly <sebastien@chimrod.com>2020-12-23 19:11:31 +0100
commitec812521b31471ce9ac3d9bdf1288b1569defbc8 (patch)
treed384c959b9e9bb2a04141ab56077026fe6e7c7f3 /script.ml
parent6354358caa1dfbf2fe1d481f6ac5fba3775938fc (diff)
Add svg output
Diffstat (limited to 'script.ml')
-rwxr-xr-xscript.ml93
1 files changed, 71 insertions, 22 deletions
diff --git a/script.ml b/script.ml
index 58eae1e..de0b48c 100755
--- a/script.ml
+++ b/script.ml
@@ -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
+ )