Skip to content

Commit

Permalink
Support for rotated nodes WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
rylin8 committed Aug 30, 2023
1 parent 5aa6ad6 commit f432d95
Show file tree
Hide file tree
Showing 14 changed files with 163 additions and 206 deletions.
17 changes: 4 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/figma_import/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ required-features = ["reflection"]
[[bin]]
name = "fetch"
path = "src/bin/fetch.rs"
required-features = ["fetch"]
required-features = ["fetch"]
8 changes: 4 additions & 4 deletions crates/figma_import/src/bin/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ fn fetch_impl(args: Args) -> Result<(), ConvertError> {
}
}

println!("### SetNodeSize 250, 24");
set_node_size(2, 250, 24);
set_node_size(5, 250, 24);
print_layout(0);
//println!("### SetNodeSize 250, 24");
//set_node_size(2, 250, 24);
//set_node_size(5, 250, 24);
//print_layout(0);

// TODO make a unit test for this below based off of #stage-replacements
/*
Expand Down
4 changes: 4 additions & 0 deletions crates/figma_import/src/figma_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,10 @@ pub struct FrameCommon {
#[serde(default)]
pub counter_axis_sizing_mode: LayoutSizingMode, // FIXED, AUTO
#[serde(default)]
pub layout_sizing_horizontal: LayoutSizing,
#[serde(default)]
pub layout_sizing_vertical: LayoutSizing,
#[serde(default)]
pub primary_axis_align_items: LayoutAlignItems, // MIN, CENTER, MAX, SPACE_BETWEEN
#[serde(default)]
pub counter_axis_align_items: LayoutAlignItems, // MIN, CENTER, MAX,
Expand Down
54 changes: 21 additions & 33 deletions crates/figma_import/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use lazy_static::lazy_static;
use log::{error, warn};
use log::error;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::sync::{Mutex, MutexGuard};
//use taffy::error::{TaffyError, TaffyResult};
use taffy::prelude::{AvailableSpace, Size, Taffy};
use taffy::tree::LayoutTree;

use crate::toolkit_schema;

// The layout response sent back to client which contains a layout state ID and
// a list of layout IDs that have changed.
#[derive(Serialize, Deserialize, Debug)]
pub struct LayoutChangedResponse {
pub layout_state: i32,
Expand All @@ -33,6 +34,7 @@ impl LayoutChangedResponse {
}
}

// Customizations that can applied to a node
struct Customizations {
sizes: HashMap<i32, Size<u32>>,
}
Expand All @@ -51,32 +53,27 @@ impl Customizations {
}

struct LayoutManager {
/*
// node id -> Taffy node used to calculate layout
node_id_to_taffy_node: HashMap<String, taffy::node::Node>,
// Taffy node -> node id
taffy_node_to_node_id: HashMap<taffy::node::Node, String>,
// top level nodes used to recompute layouts
node_queries: HashMap<NodeQuery, toolkit_schema::View>,
*/
// node id -> Taffy layout
layouts: HashMap<taffy::node::Node, toolkit_schema::Layout>,
// A struct that keeps track of all customizations
customizations: Customizations,
// Incrementing ID used to keep track of layout changes. Incremented every time relayout is done
// Incrementing ID used to keep track of layout changes. Incremented
// every time relayout is done
layout_state: i32,

// layout id -> Taffy node used to calculate layout
layout_id_to_taffy_node: HashMap<i32, taffy::node::Node>,
// Taffy node -> layout id
taffy_node_to_layout_id: HashMap<taffy::node::Node, i32>,
// layout id -> View
layout_id_to_view: HashMap<i32, toolkit_schema::View>,
// A list of root level layout IDs used to recompute layout whenever
// something has changed
root_layout_ids: HashSet<i32>,
}
impl LayoutManager {
fn new() -> Self {
LayoutManager {
//node_id_to_taffy_node: HashMap::new(),
//taffy_node_to_node_id: HashMap::new(),
//node_queries: HashMap::new(),
layouts: HashMap::new(),
customizations: Customizations::new(),
layout_state: 0,
Expand Down Expand Up @@ -203,21 +200,6 @@ impl LayoutManager {
}
}

/*
fn make_leaf_with_measure(
node_style: taffy::style::Style,
measure_func: taffy::node::MeasureFunc,
id: String,
manager: &mut LayoutManager,
taffy: &mut Taffy,
) -> TaffyResult<taffy::node::Node> {
let leaf_node = taffy.new_leaf_with_measure(node_style, measure_func)?;
manager.node_id_to_taffy_node.insert(id.clone(), leaf_node);
manager.taffy_node_to_node_id.insert(leaf_node, id);
Ok(leaf_node)
}
*/
fn add_view(
&mut self,
layout_id: i32,
Expand All @@ -229,11 +211,16 @@ impl LayoutManager {
) -> LayoutChangedResponse {
let mut taffy = taffy();

let mut node_style: taffy::style::Style = (&view.style).into();
let mut node_style: taffy::style::Style = (&view.style).into(); //(&transformed_style).into();
if view.name == "RectRot" {
//println!("### VIEWSTYLE:");
//println!("### {:#?}", view.style);
//println!("### TAFFYSTYLE:");
//println!("### {:#?}", node_style);
//println!(" ### View {} transform: {:?}", view.name, view.style.transform);
}

self.apply_variant_style(&mut node_style, &variant_view);
//warn!("### {}:", view.name);
//warn!("### {:#?}", node_style);
//warn!("###");
self.apply_customizations(layout_id, &mut node_style);

let node = self.layout_id_to_taffy_node.get(&layout_id);
Expand Down Expand Up @@ -268,6 +255,7 @@ impl LayoutManager {
self.taffy_node_to_layout_id.insert(node, layout_id);
self.layout_id_to_taffy_node.insert(layout_id, node);
self.layout_id_to_view.insert(layout_id, view.clone());
//self.layout_id_to_transforms.insert(layout_id, node_transform);
}
}
Err(e) => {
Expand Down
24 changes: 24 additions & 0 deletions crates/figma_import/src/toolkit_layout_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ pub struct Size<T> {
pub height: T,
}

impl Default for Size<f32> {
fn default() -> Self {
Size {
width: 0.0,
height: 0.0,
}
}
}

#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
pub enum AlignItems {
FlexStart,
Expand Down Expand Up @@ -325,3 +334,18 @@ impl Default for Size<Dimension> {
Self { width: Dimension::Auto, height: Dimension::Auto }
}
}

impl Dimension {
pub fn is_points(&self) -> bool {
match self {
Dimension::Points(_) => true,
_ => false
}
}
pub fn points(&self) -> f32 {
match self {
Dimension::Points(p) => *p,
_ => 0.0
}
}
}
14 changes: 13 additions & 1 deletion crates/figma_import/src/toolkit_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use crate::{
toolkit_font_style::{FontStretch, FontStyle, FontWeight},
toolkit_layout_style::{
AlignContent, AlignItems, AlignSelf, Dimension, Display, FlexDirection, FlexWrap,
JustifyContent, Number, Overflow, PositionType, Rect,
JustifyContent, Number, Overflow, PositionType, Rect, Size,
},
};

Expand Down Expand Up @@ -544,6 +544,7 @@ pub struct ViewStyle {
pub flex_grow: f32,
pub flex_shrink: f32,
pub flex_basis: Dimension,
pub bounding_box: Size<f32>,
pub width: Dimension,
pub height: Dimension,
pub min_width: Dimension,
Expand Down Expand Up @@ -606,6 +607,7 @@ impl Default for ViewStyle {
flex_grow: 0.0,
flex_shrink: 0.0,
flex_basis: Dimension::default(),
bounding_box: Size::default(),
width: Dimension::default(),
height: Dimension::default(),
min_width: Dimension::default(),
Expand Down Expand Up @@ -642,6 +644,16 @@ impl Into<taffy::Style> for &ViewStyle {
tstyle.size.width = (&self.width).into();
tstyle.size.height = (&self.height).into();

// If we have a fixed size, use the bounding box since that takes into
// account scale and rotation.
// TODO support this with non-fixed sizes also!
if self.width.is_points() {
tstyle.size.width = taffy::Dimension::Points(self.bounding_box.width);
}
if self.height.is_points() {
tstyle.size.height = taffy::Dimension::Points(self.bounding_box.height);
}

tstyle.min_size.width = (&self.min_width).into();
tstyle.min_size.height = (&self.min_height).into();
tstyle.max_size.width = (&self.max_width).into();
Expand Down
29 changes: 16 additions & 13 deletions crates/figma_import/src/transform_flexbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,15 @@ use crate::toolkit_style::{
LineHeight, MeterData, ShadowBox, StyledTextRun, TextAlign, TextOverflow, TextStyle, ViewStyle,
};

use crate::figma_schema::{TextAutoResize, TextTruncation};
use crate::vector_schema;
use crate::{
component_context::ComponentContext,
extended_layout_schema::{ExtendedAutoLayout, LayoutType, SizePolicy}, //ExtendedTextLayout
figma_schema::{
BlendMode, Component, ComponentSet, EffectType, HorizontalLayoutConstraintValue,
LayoutAlign, LayoutAlignItems, LayoutMode, LayoutSizingMode, LineHeightUnit, Node,
NodeData, PaintData, StrokeAlign, TextAlignHorizontal, TextAlignVertical, LayoutSizing,
Vector, VerticalLayoutConstraintValue,
NodeData, PaintData, StrokeAlign, TextAlignHorizontal, TextAlignVertical,
Vector, VerticalLayoutConstraintValue, LayoutSizing, TextAutoResize, TextTruncation
},
image_context::ImageContext,
reaction_schema::{FrameExtras, Reaction, ReactionJson},
Expand Down Expand Up @@ -88,6 +87,11 @@ fn compute_layout(node: &Node, parent: Option<&Node>) -> ViewStyle {
let mut hug_width = false;
let mut hug_height = false;

if let Some(bounds) = node.absolute_bounding_box {
style.bounding_box.width = bounds.width();
style.bounding_box.height = bounds.height();
}

// Frames can implement Auto Layout on their children.
if let Some(frame) = node.frame() {
style.position_type = PositionType::Relative;
Expand Down Expand Up @@ -188,16 +192,15 @@ fn compute_layout(node: &Node, parent: Option<&Node>) -> ViewStyle {
// Frame is not autolayout, so used a fixed size
style.width = dim_points_or_auto(bounds.width().ceil());
style.height = dim_points_or_auto(bounds.height().ceil());
/*
style.width = match frame.counter_axis_sizing_mode {
LayoutSizingMode::Fixed => dim_points_or_auto(bounds.width().ceil()),
LayoutSizingMode::Auto => Dimension::Auto,
};
style.height = match frame.primary_axis_sizing_mode {
LayoutSizingMode::Fixed => dim_points_or_auto(bounds.height().ceil()),
LayoutSizingMode::Auto => Dimension::Auto,
};
*/

// If we have a node size specified, use that instead. The
// node size is the size without rotation and scale.
if let Some(size) = &node.size {
if size.is_valid() {
style.width = Dimension::Points(size.x());
style.height = Dimension::Points(size.y());
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyGridScope
Expand All @@ -32,6 +33,7 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
Expand Down Expand Up @@ -147,7 +149,7 @@ internal fun DesignFrame(
// annotations set variant properties that match. If so, variantNodeName will be set to the
// name of the node with all the variants set to the @DesignVariant parameters
val variantNodeName = customizations.getMatchingVariant(componentInfo)
val layoutModifier = Modifier.layoutToModifier(layout).layoutId(layoutId)
val layoutModifier = Modifier.layoutToModifier(layout)
var m = Modifier.layoutStyle(name, style).then(layoutModifier)
// Only render the frame if we don't have a custom variant node that we are about to
// render instead
Expand Down Expand Up @@ -591,8 +593,10 @@ internal fun DesignFrame(
}
}
is LayoutInfoAbsolute -> {
println("### DesignFrame $name left ${layout?.left} width ${layout?.width}")
Box(layoutInfo.selfModifier.then(m)) {
println("### DesignFrame $name left ${layout?.left} width ${layout?.width} height ${layout?.height}")
val frameModifier = layoutInfo.selfModifier.then(m)
.wrapContentSize(align = Alignment.TopStart, unbounded = true)
Box(frameModifier) {
content()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,26 +221,6 @@ internal fun DesignText(
TextOverflow.Clip
else TextOverflow.Ellipsis

/*
val layoutModifier =
when (viewLayoutInfo) {
is LayoutInfoAbsolute -> viewLayoutInfo.marginModifier
is LayoutInfoRow -> viewLayoutInfo.marginModifier
is LayoutInfoColumn -> viewLayoutInfo.marginModifier
is LayoutInfoGrid -> viewLayoutInfo.marginModifier
else -> Modifier
}
DesignTextLayout(
layoutModifier.textTransform(style).layoutStyle(annotatedText.text, style).clipToBounds(),
style,
TextLayoutData(annotatedText, textStyle, LocalFontLoader.current),
annotatedText.text
)
*/
// Box(modifier = layoutModifier.textTransform(style).layoutStyle(annotatedText.text,
// style).clipToBounds()) {

val textLayoutData = TextLayoutData(annotatedText, textStyle, LocalFontLoader.current)
val maxLines = if (style.line_count.isPresent) style.line_count.get().toInt() else Int.MAX_VALUE
val textMeasureData = TextMeasureData(textLayoutData, density, maxLines)
Expand Down Expand Up @@ -317,7 +297,6 @@ internal fun DesignText(
// if the parent frame does not clip contents.
val layoutModifier = Modifier
.layoutToModifier(layout)
.layoutId(layoutId)
.wrapContentSize(align = Alignment.TopStart, unbounded = true)
.textTransform(style) // TODO needed?
.clipToBounds() // TODO needed?
Expand Down
Loading

0 comments on commit f432d95

Please sign in to comment.