1 ! Copyright (C) 2009 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors combinators kernel locals math math.functions
4 math.order sequences ui.gadgets ;
5 IN: ui.baseline-alignment
9 TUPLE: aligned-gadget < gadget baseline cap-height ;
11 GENERIC: baseline* ( gadget -- y )
13 GENERIC: baseline ( gadget -- y )
15 M: gadget baseline drop f ;
17 M: aligned-gadget baseline
20 [ baseline* ] [ ] [ layout-state>> ] tri
21 [ drop ] [ dupd baseline<< ] if
24 GENERIC: cap-height* ( gadget -- y )
26 GENERIC: cap-height ( gadget -- y )
28 M: gadget cap-height drop f ;
30 M: aligned-gadget cap-height
33 [ cap-height* ] [ ] [ layout-state>> ] tri
34 [ drop ] [ dupd cap-height<< ] if
39 ! Text has ascent/descent/cap-height slots, graphics does not.
40 TUPLE: gadget-metrics height ascent descent cap-height ;
42 : <gadget-metrics> ( gadget dim -- metrics )
43 second swap [ baseline ] [ cap-height ] bi
44 [ dup [ 2dup - ] [ f ] if ] dip
45 gadget-metrics boa ; inline
47 : ?supremum ( seq -- n/f )
48 sift [ f ] [ supremum ] if-empty ;
50 : max-ascent ( seq -- n )
51 [ ascent>> ] map ?supremum ;
53 : max-cap-height ( seq -- n )
54 [ cap-height>> ] map ?supremum ;
56 : max-descent ( seq -- n )
57 [ descent>> ] map ?supremum ;
59 : max-graphics-height ( seq -- y )
60 [ ascent>> not ] filter [ height>> ] map ?supremum 0 or ;
62 :: combine-metrics ( graphics-height ascent descent cap-height -- ascent' descent' )
64 cap-height 2 / :> mid-line
66 [ ascent mid-line - max mid-line + floor >integer ]
67 [ descent mid-line + max mid-line - ceiling >integer ] bi
70 : (measure-metrics) ( children sizes -- graphics-height ascent descent cap-height )
71 [ <gadget-metrics> ] 2map
73 [ max-graphics-height ]
81 :: align-baselines ( gadgets -- ys )
82 gadgets [ dup pref-dim <gadget-metrics> ] map
83 dup max-ascent 0 or :> max-ascent
84 dup max-cap-height 0 or :> max-cap-height
85 dup max-graphics-height :> max-graphics-height
87 max-cap-height max-graphics-height + 2 /i :> critical-line
88 critical-line max-ascent [-] :> text-leading
89 max-ascent critical-line [-] :> graphics-leading
93 [ ascent>> max-ascent swap - text-leading ]
94 [ height>> max-graphics-height swap - 2 /i graphics-leading ] if +
97 : measure-metrics ( children sizes -- ascent descent )
98 (measure-metrics) combine-metrics ;
100 : measure-height ( children sizes -- height )
101 (measure-metrics) dup [ combine-metrics + ] [ 3drop ] if ;