Make length (still the default for all property) be the logical length

And a new `physical_length` is now the physical_length unit

Note: this does not change the runtime part yet
This commit is contained in:
Olivier Goffart 2021-04-20 17:01:49 +02:00
parent 7ae850d564
commit 91ed04a72c
22 changed files with 66 additions and 70 deletions

View file

@ -9,8 +9,8 @@ The follow table summarizes the entire mapping:
| `float` | `float` | | | `float` | `float` | |
| `string` | [`sixtyfps::SharedString`](api/structsixtyfps_1_1_shared_string.html) | A reference-counted string type that uses UTF-8 encoding and can be easily converted to a std::string_view or a const char *. | | `string` | [`sixtyfps::SharedString`](api/structsixtyfps_1_1_shared_string.html) | A reference-counted string type that uses UTF-8 encoding and can be easily converted to a std::string_view or a const char *. |
| `color` | [`sixtyfps::Color`](api/classsixtyfps_1_1_color.html) | | | `color` | [`sixtyfps::Color`](api/classsixtyfps_1_1_color.html) | |
| `length` | `float` | The unit are physical pixels. | | `physical_length` | `float` | The unit are physical pixels. |
| `logical_length` | `float` | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. | | `length` | `float` | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. |
| `duration` | `std::int64_t` | At run-time, durations are always represented as signed 64-bit integers with milisecond precision. | | `duration` | `std::int64_t` | At run-time, durations are always represented as signed 64-bit integers with milisecond precision. |
| stucture | A `class` of the same name | The order of the data member are in the lexicographic order of their name | | stucture | A `class` of the same name | The order of the data member are in the lexicographic order of their name |

View file

@ -91,7 +91,7 @@ component.clicked();
| `string` | `String` | | | `string` | `String` | |
| `color` |`String` | Colors are represented as strings in the form `"#rrggbbaa"`. When setting a color property, any CSS compliant color is accepted as a string. | | `color` |`String` | Colors are represented as strings in the form `"#rrggbbaa"`. When setting a color property, any CSS compliant color is accepted as a string. |
| `length` | `Number` | | | `length` | `Number` | |
| `logical_length` | `Number` | | | `physical_length` | `Number` | |
| `duration` | `Number` | | | `duration` | `Number` | |
| structure | `Object` | Structures are mapped to JavaScrip objects with structure fields mapped to properties. | | structure | `Object` | Structures are mapped to JavaScrip objects with structure fields mapped to properties. |
| array | `Array` or Model Object | | | array | `Array` or Model Object | |

View file

@ -129,8 +129,8 @@ The follow table summarizes the entire mapping:
| `float` | `f32` | | | `float` | `f32` | |
| `string` | [`SharedString`] | A reference-counted string type that can be easily converted to a str reference. | | `string` | [`SharedString`] | A reference-counted string type that can be easily converted to a str reference. |
| `color` | [`Color`] | | | `color` | [`Color`] | |
| `length` | `f32` | The unit are physical pixels. | | `physicial_length` | `f32` | The unit are physical pixels. |
| `logical_length` | `f32` | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. | | `length` | `f32` | At run-time, logical lengths are automatically translated to physical pixels using the device pixel ratio. |
| `duration` | `i64` | At run-time, durations are always represented as signed 64-bit integers with milisecond precision. | | `duration` | `i64` | At run-time, durations are always represented as signed 64-bit integers with milisecond precision. |
| structure | `struct` of the same name | | | structure | `struct` of the same name | |
| array | [`ModelHandle`] | | | array | [`ModelHandle`] | |

View file

@ -192,8 +192,8 @@ All properties in elements have a type. The following types are supported:
| `string` | UTF-8 encoded, reference counted string. | | `string` | UTF-8 encoded, reference counted string. |
| `color` | RGB color with an alpha channel, with 8 bit precision for each channel. CSS color names as well as the hexadecimal color encodings are supported, such as `#RRGGBBAA` or `#RGB`. | | `color` | RGB color with an alpha channel, with 8 bit precision for each channel. CSS color names as well as the hexadecimal color encodings are supported, such as `#RRGGBBAA` or `#RGB`. |
| `brush` | A brush is a special type that can be either initialized from a color or a gradient specification. See the [Colors Section](#colors) for more information. | | `brush` | A brush is a special type that can be either initialized from a color or a gradient specification. See the [Colors Section](#colors) for more information. |
| `length` | The type used for `x`, `y`, `width` and `height` coordinates. This is an amount of physical pixels. To convert from an integer to a length unit, one can simply multiply by `1px`. Or to convert from a length to a float, one can divide by `1phx`. | | `physicial_length` | This is an amount of physical pixels. To convert from an integer to a length unit, one can simply multiply by `1px`. Or to convert from a length to a float, one can divide by `1phx`. |
| `logical_length` | Corresponds to a literal like `1px`, `1pt`, `1in`, `1mm`, or `1cm`. It can be converted to and from length provided the binding is run in a context where there is an access to the device pixel ratio. | | `length` | The type used for `x`, `y`, `width` and `height` coordinates. Corresponds to a literal like `1px`, `1pt`, `1in`, `1mm`, or `1cm`. It can be converted to and from length provided the binding is run in a context where there is an access to the device pixel ratio. |
| `duration` | Type for the duration of animations. A suffix like `ms` (milisecond) or `s` (second) is used to indicate the precision. | | `duration` | Type for the duration of animations. A suffix like `ms` (milisecond) or `s` (second) is used to indicate the precision. |
| `angle` | Angle mesurement, corresponds to a literal like `90deg`, `1.2rad`, `0.25turn` | | `angle` | Angle mesurement, corresponds to a literal like `90deg`, `1.2rad`, `0.25turn` |
| `easing` | Property animation allow specifying an easing curve. Valid values are `linear` (values are interpolated linearly) and the [four common cubiz-bezier functions known from CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#Keywords_for_common_cubic-bezier_easing_functions): `ease`, `ease_in`, `ease_in_out`, `ease_out`. | | `easing` | Property animation allow specifying an easing curve. Valid values are `linear` (values are interpolated linearly) and the [four common cubiz-bezier functions known from CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function#Keywords_for_common_cubic-bezier_easing_functions): `ease`, `ease_in`, `ease_in_out`, `ease_out`. |
@ -246,9 +246,9 @@ Example := Window {
* `int` can be converted implicitly to `float` and vice-versa * `int` can be converted implicitly to `float` and vice-versa
* `int` and `float` can be converted implicitly to `string` * `int` and `float` can be converted implicitly to `string`
* `logical_length` and `length` can be converted implictly to eachother only in * `physical_length` and `length` can be converted implictly to eachother only in
context where the pixel ratio is known. context where the pixel ratio is known.
* the units type (`length`, `logical_length`, `duration`, ...) cannot be converted to numbers (`float` or `int`) * the units type (`length`, `physical_length`, `duration`, ...) cannot be converted to numbers (`float` or `int`)
but they can be devided with themself to result in a number. Similarily, a number can be multiplied by one of but they can be devided with themself to result in a number. Similarily, a number can be multiplied by one of
these unit. The idea is that one would multiply by `1px` or divide by `1px` to do such conversions these unit. The idea is that one would multiply by `1px` or divide by `1px` to do such conversions
* The literal `0` can be converted to any of these types that have associated unit. * The literal `0` can be converted to any of these types that have associated unit.

View file

@ -56,7 +56,7 @@ export global DemoPalette := {
property <color> push_button_text_color: white; property <color> push_button_text_color: white;
property <logical_length> base_font_size: 16px; property <length> base_font_size: 16px;
property <bool> night_mode: false; property <bool> night_mode: false;
} }

View file

@ -101,7 +101,7 @@ MainWindow := Window {
width: 57px; width: 57px;
x: 10px; x: 10px;
callback icon_y(int) -> logical_length; callback icon_y(int) -> length;
icon_y(index) => { icon_y(index) => {
100px // top padding 100px // top padding
+ index * 72px; + index * 72px;

View file

@ -13,8 +13,8 @@ struct Piece := {
pos_x: int, pos_x: int,
pos_y: int, pos_y: int,
// offset in pixel from the base position for the kicking animation // offset in pixel from the base position for the kicking animation
offset_x: logical_length, offset_x: length,
offset_y: logical_length, offset_y: length,
} }
struct Theme := { struct Theme := {

View file

@ -474,8 +474,8 @@ export NativeComboBox := _ {
} }
export global NativeStyleMetrics := { export global NativeStyleMetrics := {
property <logical_length> layout_spacing; property <length> layout_spacing;
property <logical_length> layout_padding; property <length> layout_padding;
property <logical_length> text_cursor_width; property <length> text_cursor_width;
//-is_non_item_type //-is_non_item_type
} }

View file

@ -99,8 +99,8 @@ impl BuiltinFunction {
BuiltinFunction::ImplicitItemSize => Type::Function { BuiltinFunction::ImplicitItemSize => Type::Function {
return_type: Box::new(Type::Struct { return_type: Box::new(Type::Struct {
fields: [ fields: [
("width".to_string(), Type::PhysicalLength), ("width".to_string(), Type::LogicalLength),
("height".to_string(), Type::PhysicalLength), ("height".to_string(), Type::LogicalLength),
] ]
.iter() .iter()
.cloned() .cloned()

View file

@ -2121,8 +2121,7 @@ impl<'a> LayoutTreeItem<'a> {
let path_layout_item_data = let path_layout_item_data =
|elem: &ElementRc, elem_cpp: &str, component_cpp: &str| { |elem: &ElementRc, elem_cpp: &str, component_cpp: &str| {
let prop_ref = |n: &str| { let prop_ref = |n: &str| {
if elem.borrow().lookup_property(n).property_type if elem.borrow().lookup_property(n).property_type == Type::LogicalLength
== Type::PhysicalLength
{ {
format!("&{}.{}", elem_cpp, n) format!("&{}.{}", elem_cpp, n)
} else { } else {
@ -2130,8 +2129,7 @@ impl<'a> LayoutTreeItem<'a> {
} }
}; };
let prop_value = |n: &str| { let prop_value = |n: &str| {
if elem.borrow().lookup_property(n).property_type if elem.borrow().lookup_property(n).property_type == Type::LogicalLength
== Type::PhysicalLength
{ {
let value_accessor = access_member( let value_accessor = access_member(
&elem, &elem,

View file

@ -1888,8 +1888,7 @@ impl<'a> LayoutTreeItem<'a> {
let path_layout_item_data = let path_layout_item_data =
|elem: &ElementRc, elem_rs: TokenStream, component_rust: TokenStream| { |elem: &ElementRc, elem_rs: TokenStream, component_rust: TokenStream| {
let prop_ref = |n: &str| { let prop_ref = |n: &str| {
if elem.borrow().lookup_property(n).property_type if elem.borrow().lookup_property(n).property_type == Type::LogicalLength
== Type::PhysicalLength
{ {
let n = format_ident!("{}", n); let n = format_ident!("{}", n);
quote! {Some(& #elem_rs.#n)} quote! {Some(& #elem_rs.#n)}
@ -1898,8 +1897,7 @@ impl<'a> LayoutTreeItem<'a> {
} }
}; };
let prop_value = |n: &str| { let prop_value = |n: &str| {
if elem.borrow().lookup_property(n).property_type if elem.borrow().lookup_property(n).property_type == Type::LogicalLength
== Type::PhysicalLength
{ {
let accessor = access_member( let accessor = access_member(
&elem, &elem,

View file

@ -149,8 +149,8 @@ impl Display for Type {
Type::String => write!(f, "string"), Type::String => write!(f, "string"),
Type::Duration => write!(f, "duration"), Type::Duration => write!(f, "duration"),
Type::Angle => write!(f, "angle"), Type::Angle => write!(f, "angle"),
Type::PhysicalLength => write!(f, "length"), Type::PhysicalLength => write!(f, "physical_length"),
Type::LogicalLength => write!(f, "logical_length"), Type::LogicalLength => write!(f, "length"),
Type::Percent => write!(f, "percent"), Type::Percent => write!(f, "percent"),
Type::Color => write!(f, "color"), Type::Color => write!(f, "color"),
Type::Image => write!(f, "image"), Type::Image => write!(f, "image"),

View file

@ -82,7 +82,7 @@ impl LayoutItem {
let p = |unresolved_name: &str| { let p = |unresolved_name: &str| {
let PropertyLookupResult { resolved_name, property_type } = let PropertyLookupResult { resolved_name, property_type } =
e.borrow().lookup_property(unresolved_name); e.borrow().lookup_property(unresolved_name);
if property_type == Type::PhysicalLength { if property_type == Type::LogicalLength {
Some(NamedReference::new(e, resolved_name.as_ref())) Some(NamedReference::new(e, resolved_name.as_ref()))
} else { } else {
None None
@ -123,7 +123,7 @@ impl LayoutRect {
element.borrow_mut().property_declarations.insert( element.borrow_mut().property_declarations.insert(
name.to_string(), name.to_string(),
PropertyDeclaration { PropertyDeclaration {
property_type: Type::PhysicalLength, property_type: Type::LogicalLength,
node: None, node: None,
..Default::default() ..Default::default()
}, },

View file

@ -48,7 +48,7 @@ pub fn default_geometry(root_component: &Rc<Component>, diag: &mut BuildDiagnost
debug_assert!({ debug_assert!({
let PropertyLookupResult { resolved_name: _, property_type } = let PropertyLookupResult { resolved_name: _, property_type } =
elem.borrow().lookup_property(property); elem.borrow().lookup_property(property);
property_type == Type::PhysicalLength property_type == Type::LogicalLength
}); });
elem.borrow_mut().bindings.contains_key(property) elem.borrow_mut().bindings.contains_key(property)
@ -122,7 +122,7 @@ fn fix_percent_size(
parent.borrow().lookup_property(property), parent.borrow().lookup_property(property),
PropertyLookupResult { PropertyLookupResult {
resolved_name: property.into(), resolved_name: property.into(),
property_type: Type::PhysicalLength property_type: Type::LogicalLength
} }
); );
b.expression = Expression::BinaryExpression { b.expression = Expression::BinaryExpression {
@ -142,7 +142,7 @@ fn fix_percent_size(
fn make_default_100(elem: &ElementRc, parent_element: &ElementRc, property: &str) { fn make_default_100(elem: &ElementRc, parent_element: &ElementRc, property: &str) {
let PropertyLookupResult { resolved_name, property_type } = let PropertyLookupResult { resolved_name, property_type } =
parent_element.borrow().lookup_property(property); parent_element.borrow().lookup_property(property);
if property_type != Type::PhysicalLength { if property_type != Type::LogicalLength {
return; return;
} }
elem.borrow_mut().bindings.entry(resolved_name.to_string()).or_insert_with(|| { elem.borrow_mut().bindings.entry(resolved_name.to_string()).or_insert_with(|| {

View file

@ -138,7 +138,7 @@ fn create_coodiate(
parent_element parent_element
.borrow_mut() .borrow_mut()
.property_declarations .property_declarations
.insert(property_name.clone(), Type::PhysicalLength.into()); .insert(property_name.clone(), Type::LogicalLength.into());
parent_element.borrow_mut().bindings.insert(property_name.clone(), expression.into()); parent_element.borrow_mut().bindings.insert(property_name.clone(), expression.into());
NamedReference::new(parent_element, &property_name) NamedReference::new(parent_element, &property_name)
} }

View file

@ -133,7 +133,7 @@ impl Expression {
.map(|c| Self::from_codeblock_node(c.into(), ctx)) .map(|c| Self::from_codeblock_node(c.into(), ctx))
}) })
.unwrap_or(Self::Invalid); .unwrap_or(Self::Invalid);
if ctx.property_type == Type::PhysicalLength && e.ty() == Type::Percent { if ctx.property_type == Type::LogicalLength && e.ty() == Type::Percent {
// See if a conversion from percentage to lenght is allowed // See if a conversion from percentage to lenght is allowed
const RELATIVE_TO_PARENT_PROPERTIES: [&str; 2] = ["width", "height"]; const RELATIVE_TO_PARENT_PROPERTIES: [&str; 2] = ["width", "height"];
let property_name = ctx.property_name.unwrap_or_default(); let property_name = ctx.property_name.unwrap_or_default();

View file

@ -25,9 +25,9 @@ SuperSimple := Rectangle {
// ^error{Invalid argument type} // ^error{Invalid argument type}
property <int> g: min(42, 42, 42cm); property <int> g: min(42, 42, 42cm);
// ^error{Cannot convert logical_length to float} // ^error{Cannot convert length to float}
property <int> h: min(42, 42 + 1) + max(1px , 2phx); property <int> h: min(42, 42 + 1) + max(1px , 2phx);
// ^error{Cannot convert float to logical_length} // ^error{Cannot convert float to length}
} }

View file

@ -16,24 +16,24 @@ use crate::langtype::{Enumeration, Type};
use crate::object_tree::Component; use crate::object_tree::Component;
pub(crate) const RESERVED_GEOMETRY_PROPERTIES: &'static [(&'static str, Type)] = &[ pub(crate) const RESERVED_GEOMETRY_PROPERTIES: &'static [(&'static str, Type)] = &[
("x", Type::PhysicalLength), ("x", Type::LogicalLength),
("y", Type::PhysicalLength), ("y", Type::LogicalLength),
("width", Type::PhysicalLength), ("width", Type::LogicalLength),
("height", Type::PhysicalLength), ("height", Type::LogicalLength),
]; ];
const RESERVED_LAYOUT_PROPERTIES: &'static [(&'static str, Type)] = &[ const RESERVED_LAYOUT_PROPERTIES: &'static [(&'static str, Type)] = &[
("minimum_width", Type::PhysicalLength), ("minimum_width", Type::LogicalLength),
("minimum_height", Type::PhysicalLength), ("minimum_height", Type::LogicalLength),
("maximum_width", Type::PhysicalLength), ("maximum_width", Type::LogicalLength),
("maximum_height", Type::PhysicalLength), ("maximum_height", Type::LogicalLength),
("padding", Type::PhysicalLength), ("padding", Type::LogicalLength),
("padding_left", Type::PhysicalLength), ("padding_left", Type::LogicalLength),
("padding_right", Type::PhysicalLength), ("padding_right", Type::LogicalLength),
("padding_top", Type::PhysicalLength), ("padding_top", Type::LogicalLength),
("padding_bottom", Type::PhysicalLength), ("padding_bottom", Type::LogicalLength),
("preferred_width", Type::PhysicalLength), ("preferred_width", Type::LogicalLength),
("preferred_height", Type::PhysicalLength), ("preferred_height", Type::LogicalLength),
("horizontal_stretch", Type::Float32), ("horizontal_stretch", Type::Float32),
("vertical_stretch", Type::Float32), ("vertical_stretch", Type::Float32),
("col", Type::Int32), ("col", Type::Int32),
@ -50,9 +50,9 @@ const RESERVED_OTHER_PROPERTIES: &'static [(&'static str, Type)] = &[
]; ];
pub(crate) const RESERVED_DROP_SHADOW_PROPERTIES: &'static [(&'static str, Type)] = &[ pub(crate) const RESERVED_DROP_SHADOW_PROPERTIES: &'static [(&'static str, Type)] = &[
("drop_shadow_offset_x", Type::PhysicalLength), ("drop_shadow_offset_x", Type::LogicalLength),
("drop_shadow_offset_y", Type::PhysicalLength), ("drop_shadow_offset_y", Type::LogicalLength),
("drop_shadow_blur", Type::PhysicalLength), ("drop_shadow_blur", Type::LogicalLength),
("drop_shadow_color", Type::Color), ("drop_shadow_color", Type::Color),
]; ];

View file

@ -25,9 +25,9 @@ global Palette := {
} }
export global StyleMetrics := { export global StyleMetrics := {
property<logical_length> layout_spacing: 5px; property<length> layout_spacing: 5px;
property<logical_length> layout_padding: 5px; property<length> layout_padding: 5px;
property<logical_length> text_cursor_width: 2px; property<length> text_cursor_width: 2px;
property<color> window_background: #ecedeb; //FIXME: Palette.window_background does not compile (cannot access globals from other globals #175) property<color> window_background: #ecedeb; //FIXME: Palette.window_background does not compile (cannot access globals from other globals #175)
} }

View file

@ -173,11 +173,11 @@ impl RepeatedComponent for ErasedComponentBox {
let get_prop = |name: &str| { let get_prop = |name: &str| {
let PropertyLookupResult { resolved_name, property_type } = let PropertyLookupResult { resolved_name, property_type } =
root_item.borrow().lookup_property(name); root_item.borrow().lookup_property(name);
if property_type == Type::PhysicalLength { if property_type == Type::LogicalLength {
let nr = NamedReference::new(root_item, resolved_name.as_ref()); let nr = NamedReference::new(root_item, resolved_name.as_ref());
let p = get_property_ptr(&nr, s.borrow_instance()); let p = get_property_ptr(&nr, s.borrow_instance());
// Safety: assuming get_property_ptr returned a valid pointer, // Safety: assuming get_property_ptr returned a valid pointer,
// we know that `Type::PhysicalLength` is a property of type `f32` // we know that `Type::LogicalLength` is a property of type `f32`
Some(unsafe { &*(p as *const Property<f32>) }) Some(unsafe { &*(p as *const Property<f32>) })
} else { } else {
None None

View file

@ -8,15 +8,15 @@
Please contact info@sixtyfps.io for more information. Please contact info@sixtyfps.io for more information.
LICENSE END */ LICENSE END */
TestCase := Rectangle { TestCase := Rectangle {
property<length> l1: 12phx; property<physical_length> l1: 12phx;
property<length> l2: 12px; property<physical_length> l2: 12px;
property<length> l3: 100phx + 12px; property<physical_length> l3: 100phx + 12px;
property<length> l4: 120 * 1phx; property<physical_length> l4: 120 * 1phx;
property<logical_length> ll1: 12phx; property<length> ll1: 12phx;
property<logical_length> ll2: 12px; property<length> ll2: 12px;
property<logical_length> ll3: 100phx + 12px; property<length> ll3: 100phx + 12px;
property<logical_length> ll4: 120 * 1phx; property<length> ll4: 120 * 1phx;
property<bool> value: l1 == 10phx + 2phx; property<bool> value: l1 == 10phx + 2phx;

View file

@ -22,7 +22,7 @@ export const sixtyfps_language = <monaco.languages.IMonarchLanguage>{
lang_keywords: [ lang_keywords: [
'root', 'parent', 'this', 'if' 'root', 'parent', 'this', 'if'
], ],
type_keywords: ['int', 'string', 'float', 'length', 'logical_length', 'duration'], type_keywords: ['int', 'string', 'float', 'length', 'physical_length', 'duration'],
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/, escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
symbols: /[\#\!\%\&\*\+\-\.\/\:\;\<\=\>\@\^\|_\?,()]+/, symbols: /[\#\!\%\&\*\+\-\.\/\:\;\<\=\>\@\^\|_\?,()]+/,