Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clay/lynx_adaptor/painting_context_clay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ void PaintingContextClay::UpdateLayout(int tag, float x, float y, float width,
const float* margins,
const float* borders,
const float* bounds, const float* sticky,
float max_height, uint32_t node_index) {
float max_height, uint32_t node_index,
bool /*display_none*/) {
const std::array<float, 4> paddings_copy = {paddings[0], paddings[1],
paddings[2], paddings[3]};
const std::array<float, 4> margins_copy = {margins[0], margins[1], margins[2],
Expand Down
4 changes: 2 additions & 2 deletions clay/lynx_adaptor/painting_context_clay.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ class PaintingContextClay : public PaintingCtxPlatformImpl,
void UpdateLayout(int tag, float x, float y, float width, float height,
const float* paddings, const float* margins,
const float* borders, const float* bounds,
const float* sticky, float max_height,
uint32_t node_index) override;
const float* sticky, float max_height, uint32_t node_index,
bool display_none) override;
void Invoke(int64_t id, const std::string& method, const pub::Value& params,
const std::function<void(int32_t code, const pub::Value& data)>&
callback) override;
Expand Down
3 changes: 2 additions & 1 deletion core/public/painting_ctx_platform_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ class PaintingCtxPlatformImpl {
float height, const float* paddings,
const float* margins, const float* borders,
const float* bounds, const float* sticky,
float max_height, uint32_t node_index) = 0;
float max_height, uint32_t node_index,
bool display_none) = 0;
virtual void RecordInitialLynxUITreeForReplay(
std::vector<InitialLynxUITreeNodeForReplay> nodes) {}
virtual void UpdatePlatformExtraBundle(int32_t id,
Expand Down
3 changes: 2 additions & 1 deletion core/renderer/dom/element.cc
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ void Element::UpdateLayout(float left, float top, float width, float height,
const std::array<float, 4>& margins,
const std::array<float, 4>& borders,
const std::array<float, 4>* sticky_positions,
float max_height) {
float max_height, bool display_none) {
TRACE_EVENT(LYNX_TRACE_CATEGORY, ELEMENT_UPDATE_LAYOUT);
// TODO: only leaf node need to update border padding
frame_changed_ = true;
Expand All @@ -411,6 +411,7 @@ void Element::UpdateLayout(float left, float top, float width, float height,
paddings_ = paddings;
margins_ = margins;
borders_ = borders;
display_none_ = display_none;
UpdateStickyPosition(sticky_positions);
MarkSubtreeNeedUpdate();
NotifyElementSizeUpdated();
Expand Down
4 changes: 3 additions & 1 deletion core/renderer/dom/element.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ class Element : public lepus::RefCounted,
const std::array<float, 4>& margins,
const std::array<float, 4>& borders,
const std::array<float, 4>* sticky_positions,
float max_height);
float max_height, bool display_none = false);
// Used to update child element's left and top value from list element. The
// another overloaded function is used to update layout info from starlight,
// but if the element is list's child, the left and top's value are always 0.
Expand Down Expand Up @@ -878,6 +878,7 @@ class Element : public lepus::RefCounted,
float height() { return height_; }
float top() { return top_; }
float left() { return left_; }
bool display_none() { return display_none_; }

bool enable_new_animator() { return enable_new_animator_; }

Expand Down Expand Up @@ -1543,6 +1544,7 @@ class Element : public lepus::RefCounted,

bool subtree_need_update_{false};
bool frame_changed_{false};
bool display_none_{false};
// Determine by Catalyzer
bool is_layout_only_{false};

Expand Down
2 changes: 1 addition & 1 deletion core/renderer/dom/element_container.cc
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ void ElementContainer::UpdateLayout(float left, float top,
element()->height(), element()->paddings().data(),
element()->margins().data(), element()->borders().data(), nullptr,
GetStickyPositionIfNeeded(), element()->max_height(),
element()->NodeIndex());
element()->NodeIndex(), element()->display_none());
}
if (need_update_impl || props_changed_) {
painting_context()->OnNodeReady(element()->impl_id());
Expand Down
1 change: 1 addition & 0 deletions core/renderer/dom/fiber/fiber_element.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5601,6 +5601,7 @@ void FiberElement::UpdateLayoutInfo() {
borders_[1] = layout_result.border_[starlight::kTop];
borders_[2] = layout_result.border_[starlight::kRight];
borders_[3] = layout_result.border_[starlight::kBottom];
display_none_ = sl_node_->GetShouldDisplayNone();

if (IsShadowNodeCustom()) {
element_manager_->layout_context()->OnLayout(id_, left_, top_, width_,
Expand Down
21 changes: 18 additions & 3 deletions core/renderer/dom/fragment/fragment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ void Fragment::OnDraw(DisplayListBuilder& display_list_builder) {
}

void Fragment::DrawFull(DisplayListBuilder& display_list_builder) {
if (element()->IsShadowNodeVirtual()) {
if (element()->IsShadowNodeVirtual() || element()->display_none()) {
// No contents to be rendered for virtual shadow nodes.
return;
}
Expand Down Expand Up @@ -1161,9 +1161,24 @@ void Fragment::Draw() {
builder.Reserve(draw_node_capacity_);
}

OnDraw(builder);
if (!element()->display_none()) {
OnDraw(builder);

CheckRootIfNeedClipBounds(builder);
CheckRootIfNeedClipBounds(builder);
} else {
// display:none: still emit a display list containing only this node's
// Begin/End so the platform layer receives an update and clears any stale
// content / sublayers / event-target state instead of keeping the previous
// frame.
builder.Begin(id(),
behavior_ == nullptr ? PlatformRendererType::kUnknown
: behavior_->GetType(),
layout_info_.layout_result.offset_.X(),
layout_info_.layout_result.offset_.Y(),
layout_info_.layout_result.size_.width_,
layout_info_.layout_result.size_.height_);
builder.End();
}

painting_context()->impl()->CastToNativeCtx()->UpdateDisplayList(
id(), builder.Build());
Expand Down
170 changes: 167 additions & 3 deletions core/renderer/dom/fragment/fragment_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,7 @@ class TestPlatformRenderer : public PlatformRendererImpl {

protected:
void OnUpdateDisplayList(DisplayList display_list) override {
if (display_list.HasContent()) {
display_list_ = std::move(display_list);
}
display_list_ = std::move(display_list);
}
void OnUpdateAttributes(const fml::RefPtr<PropBundle>&, bool) override {}
void OnAddChild(PlatformRenderer*, int) override {}
Expand Down Expand Up @@ -144,6 +142,111 @@ class TestNativePaintingCtxPlatformRef : public NativePaintingCtxPlatformRef {
std::unordered_set<int32_t> scrollable_signs;
};

// Adapter that exposes the NativePaintingContext interface expected by
// Fragment::Draw() and forwards to a TestNativePaintingCtxPlatformRef.
class TestNativePaintingContext : public NativePaintingContext {
public:
void SetPlatformRef(TestNativePaintingCtxPlatformRef* ref) { ref_ = ref; }

void OnFirstScreen() override {}
void FinishTasmOperation(
const std::shared_ptr<PipelineOptions>& options) override {}
void FinishLayoutOperation(
const std::shared_ptr<PipelineOptions>& options) override {}
void CreatePlatformRenderer(
int id, PlatformRendererType type,
const fml::RefPtr<PropBundle>& init_data) override {
if (ref_) {
ref_->CreatePlatformRenderer(id, type, init_data);
}
}
void CreatePlatformExtendedRenderer(
int id, const base::String& tag_name,
const fml::RefPtr<PropBundle>& init_data) override {
if (ref_) {
ref_->CreatePlatformExtendedRenderer(id, tag_name, init_data);
}
}
void UpdateDisplayList(int id, DisplayList list) override {
if (ref_) {
ref_->UpdateDisplayList(id, std::move(list));
}
}
void CreateImage(int id, base::String src, float width, float height,
int32_t event_mask = 0) override {}
void UpdateTextBundle(int id, intptr_t bundle) override {}
void DestroyTextBundle(int id) override {}
void InsertListItemPaintingNode(int32_t list_id, int32_t child_id) override {}
void RemoveListItemPaintingNode(int32_t list_id, int32_t child_id) override {}
void UpdateContentOffsetForListContainer(int32_t container_id,
float content_size, float delta_x,
float delta_y,
bool is_init_scroll_offset,
bool from_layout) override {}
void ReconstructEventTargetTreeRecursively() override {
if (ref_) {
ref_->ReconstructEventTargetTreeRecursively();
}
}
void UpdatePlatformEventBundle(int id, PlatformEventBundle bundle) override {
if (ref_) {
ref_->UpdatePlatformEventBundle(id, std::move(bundle));
}
}

private:
TestNativePaintingCtxPlatformRef* ref_ = nullptr;
};

// A MockPaintingContext whose platform ref is a real
// NativePaintingCtxPlatformRef so that Fragment::Draw() can exercise
// UpdateDisplayList / event-target reconstruction paths.
class NativeMockPaintingContext : public MockPaintingContext,
public TestNativePaintingContext {
public:
NativeMockPaintingContext() {
auto ref = std::make_shared<TestNativePaintingCtxPlatformRef>();
platform_ref_ = ref;
SetPlatformRef(ref.get());
}

NativePaintingContext* CastToNativeCtx() override { return this; }

TestNativePaintingCtxPlatformRef* GetNativePlatformRef() {
return static_cast<TestNativePaintingCtxPlatformRef*>(platform_ref_.get());
}
};

class FragmentDrawTest : public ::testing::Test {
public:
FragmentDrawTest() {}
~FragmentDrawTest() override {}

void SetUp() override {
LynxEnvConfig lynx_env_config(kConfigWidth, kConfigHeight,
kDefaultLayoutsUnitPerPx,
kDefaultPhysicalPixelsPerLayoutUnit);
tasm_mediator = std::make_shared<
::testing::NiceMock<lynx::tasm::test::MockTasmDelegate>>();
manager = std::make_unique<lynx::tasm::ElementManager>(
std::make_unique<NativeMockPaintingContext>(), tasm_mediator.get(),
lynx_env_config);
auto config = std::make_shared<PageConfig>();
manager->page_options_.embedded_mode_ = static_cast<EmbeddedMode>(
static_cast<int32_t>(manager->page_options_.embedded_mode_) |
static_cast<int32_t>(EmbeddedMode::FRAGMENT_LAYER_RENDER));
manager->page_options_.embedded_mode_ = static_cast<EmbeddedMode>(
static_cast<int32_t>(manager->page_options_.embedded_mode_) |
static_cast<int32_t>(EmbeddedMode::LAYOUT_IN_ELEMENT));
config->SetEnableZIndex(true);
config->SetEnableFiberArch(true);
manager->SetConfig(config);
}

std::unique_ptr<lynx::tasm::ElementManager> manager;
std::shared_ptr<::testing::NiceMock<test::MockTasmDelegate>> tasm_mediator;
};

TEST_F(FragmentTest, CreateLayerIfNeededWritesFlattenInitData) {
auto element = manager->CreateFiberText("text");
element->MarkAsDirectChildOfCompatibleComponent(true);
Expand Down Expand Up @@ -1050,5 +1153,66 @@ TEST_F(FragmentTest, OutsetShadowWithZeroSizeElement) {
EXPECT_GE(list.GetContentOpTypesSize(), 1u);
}

TEST_F(FragmentDrawTest,
DisplayNoneEmitsEmptyDisplayListAndReconstructsExposure) {
auto page = manager->CreateFiberPage("0", 0);
ASSERT_NE(page, nullptr);
page->FlushActionsAsRoot();
ASSERT_TRUE(page->HasElementContainer());

auto* fragment = static_cast<Fragment*>(page->element_container());
ASSERT_NE(fragment, nullptr);

// Ensure the page fragment has a behavior and a backing platform renderer.
page->SetupFragmentBehavior(fragment);
auto* native_ctx = static_cast<NativeMockPaintingContext*>(
fragment->painting_context()->impl())
->GetNativePlatformRef();
ASSERT_NE(native_ctx, nullptr);
native_ctx->CreatePlatformRenderer(fragment->id(),
PlatformRendererType::kPage, nullptr);
fragment->has_platform_renderer_ = true;

starlight::LayoutResultForRendering layout;
layout.border_ = starlight::DirectionValue<float>({0.f, 0.f, 0.f, 0.f});
layout.padding_ = starlight::DirectionValue<float>({0.f, 0.f, 0.f, 0.f});
layout.size_ = FloatSize(100.f, 60.f);
fragment->UpdateLayout(layout);

// Give the page a background so the visible draw produces more than
// Begin/End.
page->computed_css_style()->background_data_ = starlight::BackgroundData();
page->computed_css_style()->background_data_->color = 0xFF00FF00;

auto renderer_it = native_ctx->renderers_.find(fragment->id());
ASSERT_NE(renderer_it, native_ctx->renderers_.end());
auto* renderer =
static_cast<TestPlatformRenderer*>(renderer_it->second.get());

// When visible, Draw() produces a display list with background content.
page->display_none_ = false;
fragment->Draw();
EXPECT_TRUE(renderer->display_list_.HasContent());
const size_t visible_op_count =
renderer->display_list_.GetContentOpTypesSize();
EXPECT_GT(visible_op_count, 2u);

// When display_none becomes true, Draw() must still send a display list that
// contains only this node's Begin/End so the platform layer clears stale
// content / sublayers / event-target state instead of keeping the previous
// frame. It must also still run ReconstructEventTargetTreeForExposure for the
// root.
page->display_none_ = true;
manager->MarkNeedReconstructEventTargetTreeForExposure();
fragment->Draw();
EXPECT_FALSE(manager->NeedReconstructEventTargetTreeForExposure());
EXPECT_TRUE(renderer->display_list_.HasContent());
EXPECT_EQ(renderer->display_list_.GetContentOpTypesSize(), 2u);
const int32_t* ops = renderer->display_list_.GetContentOpTypesData();
ASSERT_NE(ops, nullptr);
EXPECT_EQ(ops[0], static_cast<int32_t>(DisplayListOpType::kBegin));
EXPECT_EQ(ops[1], static_cast<int32_t>(DisplayListOpType::kEnd));
}

} // namespace tasm
} // namespace lynx
3 changes: 2 additions & 1 deletion core/renderer/dom/testing/fiber_mock_painting_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ void FiberMockPaintingContext::UpdatePaintingNode(
void FiberMockPaintingContext::UpdateLayout(
int tag, float x, float y, float width, float height, const float* paddings,
const float* margins, const float* borders, const float* bounds,
const float* sticky, float max_height, uint32_t node_index) {
const float* sticky, float max_height, uint32_t node_index,
bool /*display_none*/) {
EnqueueOperation([this, x, y, width, height, tag]() -> void {
if (node_map_.find(tag) == node_map_.end()) {
return;
Expand Down
4 changes: 2 additions & 2 deletions core/renderer/dom/testing/fiber_mock_painting_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ class FiberMockPaintingContext : public PaintingContextPlatformImpl {
void UpdateLayout(int tag, float x, float y, float width, float height,
const float* paddings, const float* margins,
const float* borders, const float* bounds,
const float* sticky, float max_height,
uint32_t node_index) override;
const float* sticky, float max_height, uint32_t node_index,
bool display_none) override;

void SetKeyframes(fml::RefPtr<PropBundle> keyframes_data) override;

Expand Down
3 changes: 2 additions & 1 deletion core/renderer/tasm/react/testing/mock_painting_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ class MockPaintingContext : public PaintingContextPlatformImpl {
float height, const float* paddings,
const float* margins, const float* borders,
const float* bounds, const float* sticky,
float max_height, uint32_t node_index) override {
float max_height, uint32_t node_index,
bool /*display_none*/) override {
std::lock_guard guard(lock_);

if (node_map_.find(tag) == node_map_.end()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class DelegateEmptyImpl : public LayoutContext::Delegate {
const std::array<float, 4>& margins,
const std::array<float, 4>& borders,
const std::array<float, 4>* sticky_positions,
float max_height) override {}
float max_height, bool display_none) override {}
virtual void OnLayoutAfter(const std::shared_ptr<PipelineOptions>& options,
std::unique_ptr<PlatformExtraBundleHolder> holder,
bool has_layout) override {}
Expand Down
4 changes: 3 additions & 1 deletion core/renderer/ui_wrapper/layout/layout_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -942,9 +942,11 @@ void LayoutContext::UpdateLayoutInfo(LayoutNode* node) {
}
}

bool display_none = sl_node->GetShouldDisplayNone();
delegate_->OnLayoutUpdate(
node->id(), left, top, width, height, paddings, margins, borders,
sticky_positions, sl_node->GetCSSStyle()->GetMaxHeight().GetRawValue());
sticky_positions, sl_node->GetCSSStyle()->GetMaxHeight().GetRawValue(),
display_none);

if (node->slnode()->GetSLMeasureFunc()) {
// Dispatch OnLayoutAfter to those nodes that have custom measure
Expand Down
2 changes: 1 addition & 1 deletion core/renderer/ui_wrapper/layout/layout_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class LayoutContext : public std::enable_shared_from_this<LayoutContext>,
const std::array<float, 4>& margins,
const std::array<float, 4>& borders,
const std::array<float, 4>* sticky_positions,
float max_height) = 0;
float max_height, bool display_none) = 0;
void OnLayoutAfter(const std::shared_ptr<PipelineOptions>& options) {
OnLayoutAfter(options, nullptr, false);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,8 @@ void NativePaintingCtxAndroid::CreatePlatformExtendedRenderer(
void NativePaintingCtxAndroid::UpdateLayout(
int tag, float x, float y, float width, float height, const float *paddings,
const float *margins, const float *borders, const float *bounds,
const float *sticky, float max_height, uint32_t node_index) {}
const float *sticky, float max_height, uint32_t node_index,
bool /*display_none*/) {}

void NativePaintingCtxAndroid::UpdatePlatformExtraBundle(
int32_t id, PlatformExtraBundle *bundle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ class NativePaintingCtxAndroid : public PaintingCtxPlatformImpl,
void UpdateLayout(int tag, float x, float y, float width, float height,
const float *paddings, const float *margins,
const float *borders, const float *bounds,
const float *sticky, float max_height,
uint32_t node_index) override;
const float *sticky, float max_height, uint32_t node_index,
bool display_none) override;

void UpdatePlatformExtraBundle(int32_t id,
PlatformExtraBundle *bundle) override;
Expand Down
Loading
Loading