blob: 4716ea15683ddd40c36246fe948da8388bec1d7e [file] [log] [blame]
// 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/shell/platform/embedder/embedder_layers.h"
#include <algorithm>
namespace flutter {
EmbedderLayers::EmbedderLayers(SkISize frame_size,
double device_pixel_ratio,
SkMatrix root_surface_transformation)
: frame_size_(frame_size),
device_pixel_ratio_(device_pixel_ratio),
root_surface_transformation_(root_surface_transformation) {}
EmbedderLayers::~EmbedderLayers() = default;
void EmbedderLayers::PushBackingStoreLayer(const FlutterBackingStore* store) {
FlutterLayer layer = {};
layer.struct_size = sizeof(FlutterLayer);
layer.type = kFlutterLayerContentTypeBackingStore;
layer.backing_store = store;
const auto layer_bounds =
SkRect::MakeWH(frame_size_.width(), frame_size_.height());
const auto transformed_layer_bounds =
root_surface_transformation_.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
presented_layers_.push_back(layer);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
double opacity) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeOpacity;
mutation.opacity = opacity;
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRect& rect) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRect;
mutation.clip_rect.left = rect.left();
mutation.clip_rect.top = rect.top();
mutation.clip_rect.right = rect.right();
mutation.clip_rect.bottom = rect.bottom();
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static FlutterSize VectorToSize(const SkVector& vector) {
FlutterSize size = {};
size.width = vector.x();
size.height = vector.y();
return size;
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkRRect& rrect) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeClipRoundedRect;
const auto& rect = rrect.rect();
mutation.clip_rounded_rect.rect.left = rect.left();
mutation.clip_rounded_rect.rect.top = rect.top();
mutation.clip_rounded_rect.rect.right = rect.right();
mutation.clip_rounded_rect.rect.bottom = rect.bottom();
mutation.clip_rounded_rect.upper_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperLeft_Corner));
mutation.clip_rounded_rect.upper_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kUpperRight_Corner));
mutation.clip_rounded_rect.lower_right_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerRight_Corner));
mutation.clip_rounded_rect.lower_left_corner_radius =
VectorToSize(rrect.radii(SkRRect::Corner::kLowerLeft_Corner));
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
static std::unique_ptr<FlutterPlatformViewMutation> ConvertMutation(
const SkMatrix& matrix) {
FlutterPlatformViewMutation mutation = {};
mutation.type = kFlutterPlatformViewMutationTypeTransformation;
mutation.transformation.scaleX = matrix[SkMatrix::kMScaleX];
mutation.transformation.skewX = matrix[SkMatrix::kMSkewX];
mutation.transformation.transX = matrix[SkMatrix::kMTransX];
mutation.transformation.skewY = matrix[SkMatrix::kMSkewY];
mutation.transformation.scaleY = matrix[SkMatrix::kMScaleY];
mutation.transformation.transY = matrix[SkMatrix::kMTransY];
mutation.transformation.pers0 = matrix[SkMatrix::kMPersp0];
mutation.transformation.pers1 = matrix[SkMatrix::kMPersp1];
mutation.transformation.pers2 = matrix[SkMatrix::kMPersp2];
return std::make_unique<FlutterPlatformViewMutation>(mutation);
}
void EmbedderLayers::PushPlatformViewLayer(
FlutterPlatformViewIdentifier identifier,
const EmbeddedViewParams& params) {
{
FlutterPlatformView view = {};
view.struct_size = sizeof(FlutterPlatformView);
view.identifier = identifier;
const auto& mutators = params.mutatorsStack();
std::vector<const FlutterPlatformViewMutation*> mutations_array;
for (auto i = mutators.Bottom(); i != mutators.Top(); ++i) {
const auto& mutator = *i;
switch (mutator->GetType()) {
case MutatorType::clip_rect: {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(mutator->GetRect()))
.get());
} break;
case MutatorType::clip_rrect: {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(mutator->GetRRect()))
.get());
} break;
case MutatorType::clip_path: {
// Unsupported mutation.
} break;
case MutatorType::transform: {
const auto& matrix = mutator->GetMatrix();
if (!matrix.isIdentity()) {
mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(matrix))
.get());
}
} break;
case MutatorType::opacity: {
const double opacity =
std::clamp(mutator->GetAlphaFloat(), 0.0f, 1.0f);
if (opacity < 1.0) {
mutations_array.push_back(
mutations_referenced_.emplace_back(ConvertMutation(opacity))
.get());
}
} break;
}
}
if (!mutations_array.empty()) {
// If there are going to be any mutations, they must first take into
// account the root surface transformation.
if (!root_surface_transformation_.isIdentity()) {
mutations_array.push_back(
mutations_referenced_
.emplace_back(ConvertMutation(root_surface_transformation_))
.get());
}
auto mutations =
std::make_unique<std::vector<const FlutterPlatformViewMutation*>>(
mutations_array.rbegin(), mutations_array.rend());
mutations_arrays_referenced_.emplace_back(std::move(mutations));
view.mutations_count = mutations_array.size();
view.mutations = mutations_arrays_referenced_.back().get()->data();
}
platform_views_referenced_.emplace_back(
std::make_unique<FlutterPlatformView>(view));
}
FlutterLayer layer = {};
layer.struct_size = sizeof(FlutterLayer);
layer.type = kFlutterLayerContentTypePlatformView;
layer.platform_view = platform_views_referenced_.back().get();
const auto layer_bounds =
SkRect::MakeXYWH(params.finalBoundingRect().x(), //
params.finalBoundingRect().y(), //
params.sizePoints().width() * device_pixel_ratio_, //
params.sizePoints().height() * device_pixel_ratio_ //
);
const auto transformed_layer_bounds =
root_surface_transformation_.mapRect(layer_bounds);
layer.offset.x = transformed_layer_bounds.x();
layer.offset.y = transformed_layer_bounds.y();
layer.size.width = transformed_layer_bounds.width();
layer.size.height = transformed_layer_bounds.height();
presented_layers_.push_back(layer);
}
void EmbedderLayers::InvokePresentCallback(
const PresentCallback& callback) const {
std::vector<const FlutterLayer*> presented_layers_pointers;
presented_layers_pointers.reserve(presented_layers_.size());
for (const auto& layer : presented_layers_) {
presented_layers_pointers.push_back(&layer);
}
callback(std::move(presented_layers_pointers));
}
} // namespace flutter