diff --git a/dom/src/dom/diff_utils.cc b/dom/src/dom/diff_utils.cc index a3a2d697a..d101a840b 100644 --- a/dom/src/dom/diff_utils.cc +++ b/dom/src/dom/diff_utils.cc @@ -19,10 +19,56 @@ */ #include "dom/diff_utils.h" -#include "footstone/logging.h" + #include "dom/node_props.h" +#include "footstone/logging.h" namespace hippy { inline namespace dom { + +static bool ShouldUpdateProperty(const std::string& key, const DomValueMap& old_props_map, + const DomValueMap& new_props_map) { + if (key == kMargin) { + if ((new_props_map.find(kMarginLeft) == new_props_map.end() && + old_props_map.find(kMarginLeft) != old_props_map.end()) || + (new_props_map.find(kMarginRight) == new_props_map.end() && + old_props_map.find(kMarginRight) != old_props_map.end()) || + (new_props_map.find(kMarginTop) == new_props_map.end() && + old_props_map.find(kMarginTop) != old_props_map.end()) || + (new_props_map.find(kMarginBottom) == new_props_map.end() && + old_props_map.find(kMarginBottom) != old_props_map.end())) { + return true; + } + } + + if (key == kPadding) { + if ((new_props_map.find(kPaddingLeft) == new_props_map.end() && + old_props_map.find(kPaddingLeft) != old_props_map.end()) || + (new_props_map.find(kPaddingRight) == new_props_map.end() && + old_props_map.find(kPaddingRight) != old_props_map.end()) || + (new_props_map.find(kPaddingTop) == new_props_map.end() && + old_props_map.find(kPaddingTop) != old_props_map.end()) || + (new_props_map.find(kPaddingBottom) == new_props_map.end() && + old_props_map.find(kPaddingBottom) != old_props_map.end())) { + return true; + } + } + + if (key == kBorderWidth) { + if ((new_props_map.find(kBorderLeftWidth) == new_props_map.end() && + old_props_map.find(kBorderLeftWidth) != old_props_map.end()) || + (new_props_map.find(kBorderRightWidth) == new_props_map.end() && + old_props_map.find(kBorderRightWidth) != old_props_map.end()) || + (new_props_map.find(kBorderTopWidth) == new_props_map.end() && + old_props_map.find(kBorderTopWidth) != old_props_map.end()) || + (new_props_map.find(kBorderBottomWidth) == new_props_map.end() && + old_props_map.find(kBorderBottomWidth) != old_props_map.end())) { + return true; + } + } + + return false; +} + DiffValue DiffUtils::DiffProps(const DomValueMap& old_props_map, const DomValueMap& new_props_map) { std::shared_ptr update_props = std::make_shared(); std::shared_ptr> delete_props = std::make_shared>(); @@ -58,9 +104,20 @@ DiffValue DiffUtils::DiffProps(const DomValueMap& old_props_map, const DomValueM FOOTSTONE_DCHECK(new_prop_iter->second != nullptr); // update props - if (old_prop.second == nullptr || old_prop.second.get() != new_prop_iter->second.get()) { + if (old_prop.second == nullptr || *old_prop.second != *new_prop_iter->second) { (*update_props)[key] = new_prop_iter->second; } + + // Some special layout properties should update even if the property has not changed + // Example: + // old_props_map: { margin: 10, marginBottom: 5 } + // new_props_map: { margin: 10 } + // margin should update, otherwise the layout engine will use last margin bottom value + if (old_prop.second != nullptr && *old_prop.second == *new_prop_iter->second) { + if (ShouldUpdateProperty(key, old_props_map, new_props_map)) { + (*update_props)[key] = new_prop_iter->second; + } + } } // update props (insert new prop) diff --git a/dom/src/dom/taitank_layout_node.cc b/dom/src/dom/taitank_layout_node.cc index 4418b7177..241e785f8 100644 --- a/dom/src/dom/taitank_layout_node.cc +++ b/dom/src/dom/taitank_layout_node.cc @@ -165,6 +165,21 @@ static void CheckValueType(footstone::value::HippyValue::Type type) { FOOTSTONE_DCHECK(type == footstone::value::HippyValue::Type::kNumber || type == footstone::value::HippyValue::Type::kObject); } +static float GetDefaultValue( + const std::string& key, const std::string& relation_key, + const std::unordered_map>& style_update, + const std::vector& style_delete) { + auto it = std::find(style_delete.begin(), style_delete.end(), key); + if (it == style_delete.end()) return 0; + + float default_value = 0; + if (style_update.find(relation_key) != style_update.end()) { + auto dom_value = style_update.find(relation_key)->second; + if (dom_value->IsNumber()) default_value = static_cast(dom_value->ToDoubleChecked()); + } + return default_value; +} + static LayoutMeasureMode ToLayoutMeasureMode(MeasureMode measure_mode) { if (measure_mode == MeasureMode::MEASURE_MODE_UNDEFINED) { return LayoutMeasureMode::Undefined; @@ -415,22 +430,22 @@ void TaitankLayoutNode::Parser( SET_STYLE_VALUES(Margin, Margin, 0) SET_STYLE_VALUES(Margin, MarginVertical, 0) SET_STYLE_VALUES(Margin, MarginHorizontal, 0) - SET_STYLE_VALUES(Margin, MarginLeft, 0) - SET_STYLE_VALUES(Margin, MarginRight, 0) - SET_STYLE_VALUES(Margin, MarginTop, 0) - SET_STYLE_VALUES(Margin, MarginBottom, 0) + SET_STYLE_VALUES(Margin, MarginLeft, GetDefaultValue(kMarginLeft, kMargin, style_update, style_delete)) + SET_STYLE_VALUES(Margin, MarginRight, GetDefaultValue(kMarginRight, kMargin, style_update, style_delete)) + SET_STYLE_VALUES(Margin, MarginTop, GetDefaultValue(kMarginTop, kMargin, style_update, style_delete)) + SET_STYLE_VALUES(Margin, MarginBottom, GetDefaultValue(kMarginBottom, kMargin, style_update, style_delete)) SET_STYLE_VALUES(Padding, Padding, 0) SET_STYLE_VALUES(Padding, PaddingVertical, 0) SET_STYLE_VALUES(Padding, PaddingHorizontal, 0) - SET_STYLE_VALUES(Padding, PaddingLeft, 0) - SET_STYLE_VALUES(Padding, PaddingRight, 0) - SET_STYLE_VALUES(Padding, PaddingTop, 0) - SET_STYLE_VALUES(Padding, PaddingBottom, 0) + SET_STYLE_VALUES(Padding, PaddingLeft, GetDefaultValue(kPaddingLeft, kPadding, style_update, style_delete)) + SET_STYLE_VALUES(Padding, PaddingRight, GetDefaultValue(kPaddingRight, kPadding, style_update, style_delete)) + SET_STYLE_VALUES(Padding, PaddingTop, GetDefaultValue(kPaddingTop, kPadding, style_update, style_delete)) + SET_STYLE_VALUES(Padding, PaddingBottom, GetDefaultValue(kPaddingBottom, kPadding, style_update, style_delete)) SET_STYLE_VALUES(Border, BorderWidth, 0) - SET_STYLE_VALUES(Border, BorderLeftWidth, 0) - SET_STYLE_VALUES(Border, BorderTopWidth, 0) - SET_STYLE_VALUES(Border, BorderRightWidth, 0) - SET_STYLE_VALUES(Border, BorderBottomWidth, 0) + SET_STYLE_VALUES(Border, BorderLeftWidth, GetDefaultValue(kBorderLeftWidth, kBorderWidth, style_update, style_delete)) + SET_STYLE_VALUES(Border, BorderTopWidth, GetDefaultValue(kBorderTopWidth, kBorderWidth, style_update, style_delete)) + SET_STYLE_VALUES(Border, BorderRightWidth, GetDefaultValue(kBorderRightWidth, kBorderWidth, style_update, style_delete)) + SET_STYLE_VALUES(Border, BorderBottomWidth, GetDefaultValue(kBorderBottomWidth, kBorderWidth, style_update, style_delete)) SET_STYLE_VALUES(Position, Left, NAN) SET_STYLE_VALUES(Position, Right, NAN) SET_STYLE_VALUES(Position, Top, NAN)