// Copyright 2013 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/lib/ui/compositing/scene_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/filter_layer.h" #include "flutter/flow/layers/layer.h" #include "flutter/flow/layers/layer_tree.h" #include "flutter/flow/layers/mask_layer.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/platform_view_layer.h" #include "flutter/flow/layers/shader_mask_layer.h" #include "flutter/flow/layers/texture_layer.h" #include "flutter/flow/layers/transform_layer.h" #include "flutter/fml/build_config.h" #include "flutter/lib/ui/painting/matrix.h" #include "flutter/lib/ui/painting/shader.h" #include "flutter/lib/ui/ui_dart_state.h" #include "flutter/lib/ui/window/window.h" #include "third_party/skia/include/core/SkColorFilter.h" #if defined(OS_FUCHSIA) #include "flutter/flow/layers/child_scene_layer.h" #endif namespace flutter { IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder); #define FOR_EACH_BINDING(V) \ V(SceneBuilder, pushOffset) \ V(SceneBuilder, pushTransform) \ V(SceneBuilder, pushClipRect) \ V(SceneBuilder, pushClipRRect) \ V(SceneBuilder, pushClipPath) \ V(SceneBuilder, pushOpacity) \ V(SceneBuilder, pushColorFilter) \ V(SceneBuilder, pushBackdropFilter) \ V(SceneBuilder, pushShaderMask) \ V(SceneBuilder, pushPhysicalShape) \ V(SceneBuilder, pop) \ V(SceneBuilder, addPlatformView) \ V(SceneBuilder, addRetained) \ V(SceneBuilder, addPicture) \ V(SceneBuilder, addTexture) \ V(SceneBuilder, addPerformanceOverlay) \ V(SceneBuilder, setRasterizerTracingThreshold) \ V(SceneBuilder, setCheckerboardOffscreenLayers) \ V(SceneBuilder, setCheckerboardRasterCacheImages) \ V(SceneBuilder, build) FOR_EACH_BINDING(DART_NATIVE_CALLBACK) #if defined(OS_FUCHSIA) DART_NATIVE_CALLBACK(SceneBuilder, addChildScene) #endif void SceneBuilder::RegisterNatives(tonic::DartLibraryNatives* natives) { } SceneBuilder::SceneBuilder() = default; SceneBuilder::~SceneBuilder() = default; fml::RefPtr SceneBuilder::pushTransform( tonic::Float64List& matrix4) { SkMatrix sk_matrix = ToSkMatrix(matrix4); auto layer = std::make_shared(sk_matrix); PushLayer(layer); // matrix4 has to be released before we can return another Dart object return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushOffset(double dx, double dy) { SkMatrix sk_matrix = SkMatrix::MakeTrans(dx, dy); auto layer = std::make_shared(sk_matrix); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushClipRect(double left, double right, double top, double bottom, int clipBehavior) { SkRect clipRect = SkRect::MakeLTRB(left, top, right, bottom); flutter::Clip clip_behavior = static_cast(clipBehavior); auto layer = std::make_shared(clipRect, clip_behavior); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushClipRRect(const RRect& rrect, int clipBehavior) { flutter::Clip clip_behavior = static_cast(clipBehavior); auto layer = std::make_shared(rrect.sk_rrect, clip_behavior); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushClipPath(const CanvasPath* path, int clipBehavior) { flutter::Clip clip_behavior = static_cast(clipBehavior); FML_DCHECK(clip_behavior != flutter::Clip::none); auto layer = std::make_shared(path->path(), clip_behavior); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushOpacity(int alpha, double dx, double dy) { auto layer = std::make_shared(alpha, SkPoint::Make(dx, dy)); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushColorFilter( const ColorFilter* color_filter) { auto layer = std::make_shared(color_filter->filter()); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushBackdropFilter(ImageFilter* filter) { auto layer = std::make_shared(filter->filter()); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushShaderMask(Shader* shader, double maskRectLeft, double maskRectRight, double maskRectTop, double maskRectBottom, int blendMode) { SkRect rect = SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight, maskRectBottom); auto layer = std::make_shared( shader->shader(), rect, static_cast(blendMode)); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::pushPhysicalShape(const CanvasPath* path, double elevation, int color, int shadow_color, int clipBehavior) { auto layer = std::make_shared( static_cast(color), static_cast(shadow_color), static_cast(UIDartState::Current() ->window() ->viewport_metrics() .device_pixel_ratio), static_cast( UIDartState::Current()->window()->viewport_metrics().physical_depth), static_cast(elevation), path->path(), static_cast(clipBehavior)); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::PushGradientColorMask(const SkPaint& maskPaint) { auto layer = std::make_shared(maskPaint); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::PushSvgMask(const sk_sp& svgDom, double x, double y, double scaleX, double scaleY) { auto layer = std::make_shared(x, y, scaleX, scaleY, svgDom); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::PushPathMask(const SkPaint& maskPaint, const SkPath& maskPath) { auto layer = std::make_shared(maskPaint, maskPath); PushLayer(layer); return EngineLayer::MakeRetained(layer); } fml::RefPtr SceneBuilder::PushFilter(const SkPaint& filterPaint) { auto layer = std::make_shared(filterPaint); PushLayer(layer); return EngineLayer::MakeRetained(layer); } void SceneBuilder::addRetained(fml::RefPtr retainedLayer) { if (!current_layer_) { return; } current_layer_->Add(retainedLayer->Layer()); } void SceneBuilder::pop() { if (!current_layer_) { return; } current_layer_ = current_layer_->parent(); } void SceneBuilder::addPicture(double dx, double dy, Picture* picture, int hints) { if (!current_layer_) { return; } SkPoint offset = SkPoint::Make(dx, dy); SkRect pictureRect = picture->picture()->cullRect(); pictureRect.offset(offset.x(), offset.y()); auto layer = std::make_unique( offset, UIDartState::CreateGPUObject(picture->picture()), !!(hints & 1), !!(hints & 2)); current_layer_->Add(std::move(layer)); } void SceneBuilder::addTexture(double dx, double dy, double width, double height, int64_t textureId, bool freeze, uint8_t opacity) { if (!current_layer_) { return; } auto layer = std::make_unique( SkPoint::Make(dx, dy), SkSize::Make(width, height), textureId, freeze, opacity); current_layer_->Add(std::move(layer)); } void SceneBuilder::addPlatformView(double dx, double dy, double width, double height, int64_t viewId) { if (!current_layer_) { return; } auto layer = std::make_unique( SkPoint::Make(dx, dy), SkSize::Make(width, height), viewId); current_layer_->Add(std::move(layer)); } #if defined(OS_FUCHSIA) void SceneBuilder::addChildScene(double dx, double dy, double width, double height, SceneHost* sceneHost, bool hitTestable) { if (!current_layer_) { return; } auto layer = std::make_unique( sceneHost->id(), SkPoint::Make(dx, dy), SkSize::Make(width, height), hitTestable); current_layer_->Add(std::move(layer)); } #endif // defined(OS_FUCHSIA) void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, double left, double right, double top, double bottom) { if (!current_layer_) { return; } SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); auto layer = std::make_unique(enabledOptions); layer->set_paint_bounds(rect); current_layer_->Add(std::move(layer)); } void SceneBuilder::setRasterizerTracingThreshold(uint32_t frameInterval) { rasterizer_tracing_threshold_ = frameInterval; } void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) { checkerboard_raster_cache_images_ = checkerboard; } void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) { checkerboard_offscreen_layers_ = checkerboard; } fml::RefPtr SceneBuilder::build() { fml::RefPtr scene = Scene::create( std::move(root_layer_), rasterizer_tracing_threshold_, checkerboard_raster_cache_images_, checkerboard_offscreen_layers_); ClearDartWrapper(); return scene; } void SceneBuilder::PushLayer(std::shared_ptr layer) { FML_DCHECK(layer); if (!root_layer_) { root_layer_ = std::move(layer); current_layer_ = root_layer_.get(); return; } if (!current_layer_) { return; } flutter::ContainerLayer* newLayer = layer.get(); current_layer_->Add(std::move(layer)); current_layer_ = newLayer; } } // namespace flutter