1# Stretch2
2
3[](https://github.com/DioxusLabs/stretch/actions/workflows/ci.yml)
4[](https://crates.io/crates/stretch2)
5
6> THIS IS A FORK OF THE ORIGINAL STRETCH. CURRENTLY MAINTAINED BY DIOXUS.
7
8Stretch2 is an implementation of Flexbox written in [Rust](https://www.rust-lang.org).
9The goal of stretch2 is to provide a solid foundation for layout across all platforms with a specific focus on mobile.
10Long term we want stretch2 to not only support flexbox but also many other layout algorithms such as grid layout.
11Stretch was made for and powers <https://visly.app>.
12
13## Goals
14
15Before using or contributing to stretch2 it is good to be aware of the core goals of the project. These are goals we are working towards, not necessarily features we currently support.
16
17- High performance
18- Cross platform
19- Small binary size
20- Support multiple layout systems
21- Multi-threaded layout
22- Language bindings for most common languages
23
24## Supported Platforms
25
26- Rust
27- Android
28- iOS
29- JavaScript / TypeScript
30
31## Usage
32
33Stretch2 is built in Rust but comes with bindings to multiple languages and platforms so you can use it in a way that feels natural to your project.
34
35### Rust
36
37```toml
38# Cargo.toml
39
40[dependencies]
41stretch2 = "0.3.2"
42```
43
44```rust
45// main.rs
46
47use stretch2::geometry::Size;
48use stretch2::style::*;
49
50fn main() -> Result<(), stretch2::Error> {
51 let mut stretch2 = stretch2::node::Stretch::new();
52
53 let child = stretch.new_node(
54 Style { size: Size { width: Dimension::Percent(0.5), height: Dimension::Auto }, ..Default::default() },
55 vec![],
56 )?;
57
58 let node = stretch.new_node(
59 Style {
60 size: Size { width: Dimension::Points(100.0), height: Dimension::Points(100.0) },
61 justify_content: JustifyContent::Center,
62 ..Default::default()
63 },
64 vec![child],
65 )?;
66
67 stretch.compute_layout(node, Size::undefined())?;
68 dbg!(stretch.layout(node)?);
69}
70
71```
72
73### Android
74
75```groovy
76// Build.gradle
77
78android {
79 splits {
80 abi {
81 enable true
82 }
83 }
84}
85
86dependencies {
87 implementation 'app.visly.stretch:stretch:0.3.2'
88}
89```
90
91```kotlin
92// MainActivity.kt
93
94val node = Node(
95 Style(size = Size(Dimension.Points(100f), Dimension.Points(100f)), justifyContent = JustifyContent.Center),
96 listOf(
97 Node(Style(size = Size(Dimension.Percent(0.5f), Dimension.Percent(0.5f))), listOf())
98 ))
99
100val layout = node.computeLayout(Size(null, null))
101Log.d(TAG, "width: ${layout.width}, height: ${layout.height}")
102```
103
104### iOS
105
106```ruby
107# Podfile
108
109pod 'StretchKit', '~> 0.3.2'
110```
111
112```swift
113// ViewController.swift
114
115let node = Node(
116 style: Style(size: Size(width: .points(100.0), height: .points(100.0)), justifyContent: .center),
117 children: [
118 Node(style: Style(size: Size(width: .percent(0.5), height: .percent(0.5))), children: [])
119 ])
120
121let layout = node.computeLayout(thatFits: Size(width: nil, height: nil))
122print("width: \(layout.width), height: \(layout.height)")
123```
124
125### JavaScript
126
127```bash
128> npm install --save stretch-layout
129```
130
131```javascript
132// index.js
133
134import { Allocator, Node, JustifyContent } from 'stretch-layout';
135
136const allocator = new Allocator();
137const node = new Node(allocator, {width: 100, height: 100, justifyContent: JustifyContent.Center});
138node.addChild(new Node(allocator, {width: '50%', height: '50%'}));
139const layout = node.computeLayout();
140
141console.log(layout.width, layout.height);
142```
143
144### Installation
145
146If you don't have Rust installed you have to do that first as well as install some components that we make use of to format and lint the codebase. For more on Rust see their [website](https://www.rust-lang.org).
147
148```bash
149curl https://sh.rustup.rs -sSf | sh
150rustup component add rustfmt
151rustup component add clippy
152```
153
154Once that is done you can clone the repo and do some sanity checks to make sure everything is working correctly.
155
156```bash
157git clone https://github.com/vislyhq/stretch.git
158cd stretch
159cargo test
160```
161
162If you have made any changes to the API you should also update and run tests for all the platform bindings located in `/bindings/*`.
163
164### Testing
165
166Stretch2 is tested by validating that layouts written in stretch2 perform the same as in Chrome.
167This is done by rendering an equivalent layout in HTML and then generating a Rust test case which asserts that the resulting layout is the same when run through stretch.
168
169You can run these tests without setting up a webdriver environment but if you are looking to add any test case you will need to install [chromedriver](http://chromedriver.chromium.org).
170If you are developing on macOS this is easy to do through brew.
171
172```bash
173brew tap homebrew/cask
174brew cask install chromedriver
175```
176
177Once you have chromedriver installed and available in `PATH` you can re-generate all tests by running `cargo run --package gentest`.
178
179To add a new test case add another HTML file to `/test_fixtures` following the current tests as a template for new tests.
180
181### Benchmarking
182
183Benchmarks build on the same infrastructure as testing, and actually benchmarks are automatically generated from test fixtures just like tests.
184Run `cargo bench` to run benchmarks locally.
185
186## Relationship to Yoga
187
188[Yoga](https://www.yogalayout.com) is a cross-platform implementation of Flexbox written in C.
189Yoga is a fantastic project but has some fundamental issues which we hope to resolve.
190Compared to Yoga we aim to have a stronger adherence to web standards, a flexible architecture eventually supporting multiple layout algorithms, and future performance improvements including multi-threaded layout.
191In addition to this we aim to use a safer language with a more modern codebase.
README.md
Stretch2

THIS IS A FORK OF THE ORIGINAL STRETCH. CURRENTLY MAINTAINED BY DIOXUS.
Stretch2 is an implementation of Flexbox written in Rust.
The goal of stretch2 is to provide a solid foundation for layout across all platforms with a specific focus on mobile.
Long term we want stretch2 to not only support flexbox but also many other layout algorithms such as grid layout.
Stretch was made for and powers https://visly.app.
Goals
Before using or contributing to stretch2 it is good to be aware of the core goals of the project. These are goals we are working towards, not necessarily features we currently support.
- High performance
- Cross platform
- Small binary size
- Support multiple layout systems
- Multi-threaded layout
- Language bindings for most common languages
Supported Platforms
- Rust
- Android
- iOS
- JavaScript / TypeScript
Usage
Stretch2 is built in Rust but comes with bindings to multiple languages and platforms so you can use it in a way that feels natural to your project.
Rust
# Cargo.toml
[dependencies]
stretch2 = "0.3.2"
// main.rs
use stretch2::geometry::Size;
use stretch2::style::*;
fn main() -> Result<(), stretch2::Error> {
let mut stretch2 = stretch2::node::Stretch::new();
let child = stretch.new_node(
Style { size: Size { width: Dimension::Percent(0.5), height: Dimension::Auto }, ..Default::default() },
vec![],
)?;
let node = stretch.new_node(
Style {
size: Size { width: Dimension::Points(100.0), height: Dimension::Points(100.0) },
justify_content: JustifyContent::Center,
..Default::default()
},
vec![child],
)?;
stretch.compute_layout(node, Size::undefined())?;
dbg!(stretch.layout(node)?);
}
Android
// Build.gradle
android {
splits {
abi {
enable true
}
}
}
dependencies {
implementation 'app.visly.stretch:stretch:0.3.2'
}
// MainActivity.kt
val node = Node(
Style(size = Size(Dimension.Points(100f), Dimension.Points(100f)), justifyContent = JustifyContent.Center),
listOf(
Node(Style(size = Size(Dimension.Percent(0.5f), Dimension.Percent(0.5f))), listOf())
))
val layout = node.computeLayout(Size(null, null))
Log.d(TAG, "width: ${layout.width}, height: ${layout.height}")
iOS
# Podfile
pod 'StretchKit', '~> 0.3.2'
// ViewController.swift
let node = Node(
style: Style(size: Size(width: .points(100.0), height: .points(100.0)), justifyContent: .center),
children: [
Node(style: Style(size: Size(width: .percent(0.5), height: .percent(0.5))), children: [])
])
let layout = node.computeLayout(thatFits: Size(width: nil, height: nil))
print("width: \(layout.width), height: \(layout.height)")
JavaScript
> npm install --save stretch-layout
// index.js
import { Allocator, Node, JustifyContent } from 'stretch-layout';
const allocator = new Allocator();
const node = new Node(allocator, {width: 100, height: 100, justifyContent: JustifyContent.Center});
node.addChild(new Node(allocator, {width: '50%', height: '50%'}));
const layout = node.computeLayout();
console.log(layout.width, layout.height);
Installation
If you don't have Rust installed you have to do that first as well as install some components that we make use of to format and lint the codebase. For more on Rust see their website.
curl https://sh.rustup.rs -sSf | sh
rustup component add rustfmt
rustup component add clippy
Once that is done you can clone the repo and do some sanity checks to make sure everything is working correctly.
git clone https://github.com/vislyhq/stretch.git
cd stretch
cargo test
If you have made any changes to the API you should also update and run tests for all the platform bindings located in /bindings/*.
Testing
Stretch2 is tested by validating that layouts written in stretch2 perform the same as in Chrome.
This is done by rendering an equivalent layout in HTML and then generating a Rust test case which asserts that the resulting layout is the same when run through stretch.
You can run these tests without setting up a webdriver environment but if you are looking to add any test case you will need to install chromedriver.
If you are developing on macOS this is easy to do through brew.
brew tap homebrew/cask
brew cask install chromedriver
Once you have chromedriver installed and available in PATH you can re-generate all tests by running cargo run --package gentest.
To add a new test case add another HTML file to /test_fixtures following the current tests as a template for new tests.
Benchmarking
Benchmarks build on the same infrastructure as testing, and actually benchmarks are automatically generated from test fixtures just like tests.
Run cargo bench to run benchmarks locally.
Relationship to Yoga
Yoga is a cross-platform implementation of Flexbox written in C.
Yoga is a fantastic project but has some fundamental issues which we hope to resolve.
Compared to Yoga we aim to have a stronger adherence to web standards, a flexible architecture eventually supporting multiple layout algorithms, and future performance improvements including multi-threaded layout.
In addition to this we aim to use a safer language with a more modern codebase.