| // 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 { |
| |
| DefaultLayerBuilder::DefaultLayerBuilder() { |
| cull_rects_.push(SkRect::MakeLargest()); |
| } |
| |
| 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 = SkRect::MakeLargest(); |
| } |
| |
| auto layer = std::make_unique<flow::TransformLayer>(); |
| 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<flow::ClipRectLayer>(); |
| 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<flow::ClipRRectLayer>(); |
| 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<flow::ClipPathLayer>(); |
| layer->set_clip_path(path); |
| PushLayer(std::move(layer), cullRect); |
| } |
| |
| void DefaultLayerBuilder::PushOpacity(int alpha) { |
| auto layer = std::make_unique<flow::OpacityLayer>(); |
| layer->set_alpha(alpha); |
| PushLayer(std::move(layer), cull_rects_.top()); |
| } |
| |
| void DefaultLayerBuilder::PushColorFilter(SkColor color, |
| SkBlendMode blend_mode) { |
| auto layer = std::make_unique<flow::ColorFilterLayer>(); |
| layer->set_color(color); |
| layer->set_blend_mode(blend_mode); |
| PushLayer(std::move(layer), cull_rects_.top()); |
| } |
| |
| void DefaultLayerBuilder::PushBackdropFilter(sk_sp<SkImageFilter> filter) { |
| auto layer = std::make_unique<flow::BackdropFilterLayer>(); |
| layer->set_filter(filter); |
| PushLayer(std::move(layer), cull_rects_.top()); |
| } |
| |
| void DefaultLayerBuilder::PushShaderMask(sk_sp<SkShader> shader, |
| const SkRect& rect, |
| SkBlendMode blend_mode) { |
| auto layer = std::make_unique<flow::ShaderMaskLayer>(); |
| 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<flow::PhysicalShapeLayer>(); |
| 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<flow::PerformanceOverlayLayer>(enabled_options); |
| layer->set_paint_bounds(rect); |
| current_layer_->Add(std::move(layer)); |
| } |
| |
| void DefaultLayerBuilder::PushPicture(const SkPoint& offset, |
| sk_sp<SkPicture> 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<flow::PictureLayer>(); |
| 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<flow::TextureLayer>(); |
| 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<flow::ExportNodeHolder> 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<flow::ChildSceneLayer>(); |
| 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<flow::Layer> DefaultLayerBuilder::TakeLayer() { |
| return std::move(root_layer_); |
| } |
| |
| void DefaultLayerBuilder::PushLayer(std::unique_ptr<flow::ContainerLayer> 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 |