File tree Expand file tree Collapse file tree 3 files changed +68
-6
lines changed Expand file tree Collapse file tree 3 files changed +68
-6
lines changed Original file line number Diff line number Diff line change @@ -145,14 +145,12 @@ let rec layout_item ~duration (i : item) =
145145 let itv = Itv. create intervals in
146146 let height = ref i.height in
147147 intervals |> List. to_seq |> Seq. drop n_ccs |> Seq. iter (fun (interval : _ Itv.interval ) ->
148- let y = ref 1 in
149- let adjust other =
150- y := max ! y (other.y + other.height);
151- in
148+ let space = Space. create 1 in
149+ let adjust other = Space. mark_range space other.y (other.y + other.height) in
152150 Itv. iter_overlaps adjust interval.start interval.stop itv;
153151 let f = interval.Itv. value in
154152 layout_item ~duration f;
155- f.y < - ! y ;
153+ f.y < - Space. first_free space f.height ;
156154 height := max ! height (f.y + f.height);
157155 );
158156 i.height < - ! height
Original file line number Diff line number Diff line change 1+ (* Tracks which of a set of rows have free space.
2+ For large sets it might be more efficient to use an integer tree,
3+ but layouts that large are fairly unusable anyway. *)
4+
5+ type t = {
6+ start : int ;
7+ mutable buf : bytes ;
8+ }
9+
10+ let create start = { start; buf = Bytes. empty }
11+
12+ let mark t row =
13+ let i = row - t.start in
14+ if i > = 0 then (
15+ let byte = i lsr 3 in
16+ if byte > = Bytes. length t.buf then (
17+ let old_buf = t.buf in
18+ let old_len = Bytes. length old_buf in
19+ let new_len = max (byte + 1 ) (old_len * 2 ) in
20+ let new_buf = Bytes. extend old_buf 0 (new_len - old_len) in
21+ Bytes. fill new_buf old_len (new_len - old_len) (Char. chr 0 );
22+ t.buf < - new_buf
23+ );
24+ let buf = t.buf in
25+ let v = Bytes. get_uint8 buf byte lor (1 lsl (i land 0x7 )) in
26+ Bytes. set_uint8 buf byte v
27+ )
28+
29+ let mark_range t a b =
30+ let a = max a t.start in
31+ for i = a to b - 1 do
32+ mark t i
33+ done
34+
35+ let rec find_free_bit v start =
36+ if v land 1 = 0 then start
37+ else find_free_bit (v lsr 1 ) (start + 1 )
38+
39+ let (.%[]) t row =
40+ let i = row - t.start in
41+ let buf = t.buf in
42+ let byte = i lsr 3 in
43+ if byte > = Bytes. length buf then false
44+ else (Bytes. get_uint8 buf byte land (1 lsl (i land 7 ))) <> 0
45+
46+ let first_free t len =
47+ assert (len > = 0 );
48+ let rec check i need =
49+ if need = 0 then i - len
50+ else if t.% [i] then check (i + 1 ) len
51+ else check (i + 1 ) (need - 1 )
52+ in
53+ check t.start len
Original file line number Diff line number Diff line change 11module Itv = Eio_trace. Itv
2+ module Space = Eio_trace. Space
23
34let span = Crowbar. (map [uint8; uint8]) (fun start len -> (float start, float (start + len)))
45
@@ -24,5 +25,15 @@ let test_ivt spans (start, stop) =
2425 )
2526 )
2627
28+ let test_space start used height =
29+ let s = Space. create start in
30+ List. iter (Space. mark s) used;
31+ let free = Space. first_free s height in
32+ for i = free to free + height - 1 do
33+ if List. mem i used then
34+ Crowbar. failf " Row %d is used, but was returned as free (%d+%d)!" i free height
35+ done
36+
2737let () =
28- Crowbar. (add_test ~name: " ivt" [list span; span] test_ivt)
38+ Crowbar. (add_test ~name: " ivt" [list span; span] test_ivt);
39+ Crowbar. (add_test ~name: " space" [int8; list int8; uint8] test_space)
You can’t perform that action at this time.
0 commit comments