// Copyright 2017 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "flutter/flow/layers/default_layer_builder.h" #include "flutter/flow/layers/backdrop_filter_layer.h" #include "flutter/flow/layers/clip_path_layer.h" #include "flutter/flow/layers/clip_rect_layer.h" #include "flutter/flow/layers/clip_rrect_layer.h" #include "flutter/flow/layers/color_filter_layer.h" #include "flutter/flow/layers/container_layer.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/layers/opacity_layer.h" #include "flutter/flow/layers/performance_overlay_layer.h" #include "flutter/flow/layers/physical_shape_layer.h" #include "flutter/flow/layers/picture_layer.h" #include "flutter/flow/layers/shader_mask_layer.h" #include "flutter/flow/layers/texture_layer.h" #include "flutter/flow/layers/transform_layer.h" #if defined(OS_FUCHSIA) #include "flutter/flow/layers/child_scene_layer.h" #endif // defined(OS_FUCHSIA) namespace flow { static const SkRect kGiantRect = SkRect::MakeLTRB( -1E9F, -1E9F, 1E9F, 1E9F ); DefaultLayerBuilder::DefaultLayerBuilder() { cull_rects_.push(kGiantRect); } DefaultLayerBuilder::~DefaultLayerBuilder() = default; void DefaultLayerBuilder::PushTransform(const SkMatrix& sk_matrix) { SkMatrix inverse_sk_matrix; SkRect cullRect; if (sk_matrix.invert(&inverse_sk_matrix)) { inverse_sk_matrix.mapRect(&cullRect, cull_rects_.top()); } else { cullRect = kGiantRect; } auto layer = std::make_unique(); layer->set_transform(sk_matrix); PushLayer(std::move(layer), cullRect); } void DefaultLayerBuilder::PushClipRect(const SkRect& clipRect) { SkRect cullRect; if (!cullRect.intersect(clipRect, cull_rects_.top())) { cullRect = SkRect::MakeEmpty(); } auto layer = std::make_unique(); layer->set_clip_rect(clipRect); PushLayer(std::move(layer), cullRect); } void DefaultLayerBuilder::PushClipRoundedRect(const SkRRect& rrect) { SkRect cullRect; if (!cullRect.intersect(rrect.rect(), cull_rects_.top())) { cullRect = SkRect::MakeEmpty(); } auto layer = std::make_unique(); layer->set_clip_rrect(rrect); PushLayer(std::move(layer), cullRect); } void DefaultLayerBuilder::PushClipPath(const SkPath& path) { SkRect cullRect; if (!cullRect.intersect(path.getBounds(), cull_rects_.top())) { cullRect = SkRect::MakeEmpty(); } auto layer = std::make_unique(); layer->set_clip_path(path); PushLayer(std::move(layer), cullRect); } void DefaultLayerBuilder::PushOpacity(int alpha) { auto layer = std::make_unique(); layer->set_alpha(alpha); PushLayer(std::move(layer), cull_rects_.top()); } void DefaultLayerBuilder::PushColorFilter(SkColor color, SkBlendMode blend_mode) { auto layer = std::make_unique(); layer->set_color(color); layer->set_blend_mode(blend_mode); PushLayer(std::move(layer), cull_rects_.top()); } void DefaultLayerBuilder::PushBackdropFilter(sk_sp filter) { auto layer = std::make_unique(); layer->set_filter(filter); PushLayer(std::move(layer), cull_rects_.top()); } void DefaultLayerBuilder::PushShaderMask(sk_sp shader, const SkRect& rect, SkBlendMode blend_mode) { auto layer = std::make_unique(); layer->set_shader(shader); layer->set_mask_rect(rect); layer->set_blend_mode(blend_mode); PushLayer(std::move(layer), cull_rects_.top()); } void DefaultLayerBuilder::PushPhysicalShape(const SkPath& sk_path, double elevation, SkColor color, SkColor shadow_color, SkScalar device_pixel_ratio) { SkRect cullRect; if (!cullRect.intersect(sk_path.getBounds(), cull_rects_.top())) { cullRect = SkRect::MakeEmpty(); } auto layer = std::make_unique(); layer->set_path(sk_path); layer->set_elevation(elevation); layer->set_color(color); layer->set_shadow_color(shadow_color); layer->set_device_pixel_ratio(device_pixel_ratio); PushLayer(std::move(layer), cullRect); } void DefaultLayerBuilder::PushPerformanceOverlay(uint64_t enabled_options, const SkRect& rect) { if (!current_layer_) { return; } auto layer = std::make_unique(enabled_options); layer->set_paint_bounds(rect); current_layer_->Add(std::move(layer)); } void DefaultLayerBuilder::PushPicture(const SkPoint& offset, sk_sp picture, bool picture_is_complex, bool picture_will_change) { if (!current_layer_) { return; } SkRect pictureRect = picture->cullRect(); pictureRect.offset(offset.x(), offset.y()); if (!SkRect::Intersects(pictureRect, cull_rects_.top())) { return; } auto layer = std::make_unique(); layer->set_offset(offset); layer->set_picture(picture); layer->set_is_complex(picture_is_complex); layer->set_will_change(picture_will_change); current_layer_->Add(std::move(layer)); } void DefaultLayerBuilder::PushTexture(const SkPoint& offset, const SkSize& size, int64_t texture_id) { if (!current_layer_) { return; } auto layer = std::make_unique(); layer->set_offset(offset); layer->set_size(size); layer->set_texture_id(texture_id); current_layer_->Add(std::move(layer)); } #if defined(OS_FUCHSIA) void DefaultLayerBuilder::PushChildScene( const SkPoint& offset, const SkSize& size, fxl::RefPtr export_token_holder, bool hit_testable) { if (!current_layer_) { return; } SkRect sceneRect = SkRect::MakeXYWH(offset.x(), offset.y(), size.width(), size.height()); if (!SkRect::Intersects(sceneRect, cull_rects_.top())) { return; } auto layer = std::make_unique(); layer->set_offset(offset); layer->set_size(size); layer->set_export_node_holder(std::move(export_token_holder)); layer->set_hit_testable(hit_testable); current_layer_->Add(std::move(layer)); } #endif // defined(OS_FUCHSIA) void DefaultLayerBuilder::Pop() { if (!current_layer_) { return; } cull_rects_.pop(); current_layer_ = current_layer_->parent(); } std::unique_ptr DefaultLayerBuilder::TakeLayer() { return std::move(root_layer_); } void DefaultLayerBuilder::PushLayer(std::unique_ptr layer, const SkRect& cullRect) { FXL_DCHECK(layer); cull_rects_.push(cullRect); if (!root_layer_) { root_layer_ = std::move(layer); current_layer_ = root_layer_.get(); return; } if (!current_layer_) { return; } flow::ContainerLayer* newLayer = layer.get(); current_layer_->Add(std::move(layer)); current_layer_ = newLayer; } } // namespace flow