From a9a1455bf721f896678395dff4967094ca88bab4 Mon Sep 17 00:00:00 2001 From: chenyefu Date: Thu, 6 Feb 2025 14:45:53 +0800 Subject: [PATCH] hello world Signed-off-by: chenyefu --- lib/ui/BUILD.gn | 9 + lib/ui/compositing/scene_builder.cc | 43 +++ lib/ui/compositing/scene_builder.h | 14 + lib/ui/geometry.h | 34 +++ lib/ui/helloworld.cc | 330 ++++++++++++++++++++++++ lib/ui/helloworld.h | 240 +++++++++++++++++ lib/ui/painting/picture_recorder.cc | 16 ++ lib/ui/painting/picture_recorder.h | 1 + lib/ui/platform_dispatcher.cc | 42 +++ lib/ui/platform_dispatcher.h | 46 ++++ lib/ui/text.cc | 45 ++++ lib/ui/text.h | 66 +++++ lib/ui/text/paragraph_builder.cc | 50 ++++ lib/ui/text/paragraph_builder.h | 4 + lib/ui/window.cc | 16 ++ lib/ui/window.h | 28 ++ lib/ui/window/platform_configuration.cc | 97 ++----- runtime/BUILD.gn | 2 + runtime/capsule.cc | 25 ++ runtime/capsule.h | 47 ++++ runtime/runtime_controller.cc | 53 +++- runtime/runtime_controller.h | 6 + shell/common/animator.cc | 1 + shell/common/engine.cc | 28 +- shell/common/engine.h | 2 + shell/common/shell.cc | 2 +- 26 files changed, 1165 insertions(+), 82 deletions(-) create mode 100644 lib/ui/geometry.h create mode 100644 lib/ui/helloworld.cc create mode 100644 lib/ui/helloworld.h create mode 100644 lib/ui/platform_dispatcher.cc create mode 100644 lib/ui/platform_dispatcher.h create mode 100644 lib/ui/text.cc create mode 100644 lib/ui/text.h create mode 100644 lib/ui/window.cc create mode 100644 lib/ui/window.h create mode 100644 runtime/capsule.cc create mode 100644 runtime/capsule.h diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 1d00f1dfeb..617321590c 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -38,6 +38,9 @@ source_set("ui") { "dart_ui.h", "dart_wrapper.h", "floating_point.h", + "geometry.h", + "helloworld.cc", + "helloworld.h", "io_manager.cc", "io_manager.h", "isolate_name_server/isolate_name_server.cc", @@ -109,6 +112,8 @@ source_set("ui") { "painting/single_frame_codec.h", "painting/vertices.cc", "painting/vertices.h", + "platform_dispatcher.cc", + "platform_dispatcher.h", "plugins/callback_cache.cc", "plugins/callback_cache.h", "semantics/custom_accessibility_action.cc", @@ -122,6 +127,8 @@ source_set("ui") { "semantics/string_attribute.cc", "semantics/string_attribute.h", "snapshot_delegate.h", + "text.cc", + "text.h", "text/asset_manager_font_provider.cc", "text/asset_manager_font_provider.h", "text/font_collection.cc", @@ -134,6 +141,8 @@ source_set("ui") { "ui_dart_state.h", "volatile_path_tracker.cc", "volatile_path_tracker.h", + "window.cc", + "window.h", "window/key_data.cc", "window/key_data.h", "window/key_data_packet.cc", diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc index 6f535f301e..b3f7f37994 100644 --- a/lib/ui/compositing/scene_builder.cc +++ b/lib/ui/compositing/scene_builder.cc @@ -41,6 +41,20 @@ SceneBuilder::SceneBuilder() { SceneBuilder::~SceneBuilder() = default; +fml::RefPtr SceneBuilder::pushTransform2(const SkM44 &sk_matrix, + const fml::RefPtr& oldLayer) { + auto layer = std::make_shared(sk_matrix); + PushLayer(layer); + // matrix4 has to be released before we can return another Dart object + auto engine_layer = fml::MakeRefCounted(layer); + + if (oldLayer && oldLayer->Layer()) { + layer->AssignOldLayer(oldLayer->Layer().get()); + } + FML_LOG(ERROR) << __FILE__ << ":" <<__LINE__ << ":" << std::this_thread::get_id() << "================,SceneBuilder::pushTransform2"; + return engine_layer; +} + void SceneBuilder::pushTransform(Dart_Handle layer_handle, tonic::Float64List& matrix4, const fml::RefPtr& oldLayer) { @@ -70,6 +84,25 @@ void SceneBuilder::pushOffset(Dart_Handle layer_handle, } } +fml::RefPtr SceneBuilder::pushClipRect2(double left, + double right, + double top, + double bottom, + flutter::Clip clipBehavior, + const fml::RefPtr& oldLayer) { + SkRect clipRect = SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top), + SafeNarrow(right), SafeNarrow(bottom)); + auto layer = std::make_shared(clipRect, clipBehavior); + PushLayer(layer); + auto engine_layer = fml::MakeRefCounted(layer); + + if (oldLayer && oldLayer->Layer()) { + layer->AssignOldLayer(oldLayer->Layer().get()); + } + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,SceneBuilder::pushClipRect2"; + return engine_layer; +} + void SceneBuilder::pushClipRect(Dart_Handle layer_handle, double left, double right, @@ -280,6 +313,16 @@ void SceneBuilder::setCheckerboardOffscreenLayers(bool checkerboard) { checkerboard_offscreen_layers_ = checkerboard; } +fml::RefPtr SceneBuilder::build2() { + FML_DCHECK(layer_stack_.size() >= 1); + + auto scene = fml::MakeRefCounted(std::move(layer_stack_[0]), rasterizer_tracing_threshold_, + checkerboard_raster_cache_images_, checkerboard_offscreen_layers_); + layer_stack_.clear(); + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,SceneBuilder::build2"; + return scene; +} + void SceneBuilder::build(Dart_Handle scene_handle) { FML_DCHECK(layer_stack_.size() >= 1); diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h index dc9255cf47..50474b1bda 100644 --- a/lib/ui/compositing/scene_builder.h +++ b/lib/ui/compositing/scene_builder.h @@ -42,6 +42,10 @@ class SceneBuilder : public RefCountedDartWrappable { tonic::Float64List matrix4(matrix4_handle); pushTransform(layer_handle, matrix4, oldLayer); } + + fml::RefPtr pushTransform2(const SkM44 &sk_matrix, + const fml::RefPtr& oldLayer=nullptr); + void pushTransform(Dart_Handle layer_handle, tonic::Float64List& matrix4, const fml::RefPtr& oldLayer); @@ -49,6 +53,14 @@ class SceneBuilder : public RefCountedDartWrappable { double dx, double dy, const fml::RefPtr& oldLayer); + + fml::RefPtr pushClipRect2(double left, + double right, + double top, + double bottom, + flutter::Clip clipBehavior, + const fml::RefPtr& oldLayer=nullptr); + void pushClipRect(Dart_Handle layer_handle, double left, double right, @@ -121,6 +133,8 @@ class SceneBuilder : public RefCountedDartWrappable { void setCheckerboardRasterCacheImages(bool checkerboard); void setCheckerboardOffscreenLayers(bool checkerboard); + fml::RefPtr build2(); + void build(Dart_Handle scene_handle); const std::vector>& layer_stack() { diff --git a/lib/ui/geometry.h b/lib/ui/geometry.h new file mode 100644 index 0000000000..707eb46415 --- /dev/null +++ b/lib/ui/geometry.h @@ -0,0 +1,34 @@ +#ifndef KEELS_LIB_UI_GEOMETRY_H_ +#define KEELS_LIB_UI_GEOMETRY_H_ + +namespace keels{ + +struct Size{ + Size(double w=0.0, double h=0.0): width(w), height(h){} + double width; + double height; +}; + +constexpr double _giantScalar = 1.0E+9; +struct Rect{ + Rect(double l, double t, double r, double b):left(l),top(t),right(r),bottom(b){} + static Rect largest() {return Rect(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar); } + double width() const {return right-left;} + double height() const {return bottom-top;} + Size size() const {return Size(width(), height());} + + double left; + double top; + double right; + double bottom; +}; + +struct Offset{ + Offset(double x, double y):dx(x),dy(y){} + double dx; + double dy; +}; + +}; + +#endif \ No newline at end of file diff --git a/lib/ui/helloworld.cc b/lib/ui/helloworld.cc new file mode 100644 index 0000000000..6ec156d5ec --- /dev/null +++ b/lib/ui/helloworld.cc @@ -0,0 +1,330 @@ +#include "flutter/lib/ui/helloworld.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/lib/ui/floating_point.h" +#include +#include +namespace keels{ + +TextSpan::TextSpan(const std::u16string& text): text_(text) { +} + +void TextSpan::build(fml::RefPtr builder) { + builder->addText2(text_); +} + +ParagraphStyle TextStyle::getParagraphStyle(const TextAlign &textAlign, + const TextDirection &textDirection, + const TextScaler &textScaler) { + return ParagraphStyle(textAlign, textDirection, textScaler.scale(kDefaultFontSize)); +} + + +double TextLayout::_contentWidthFor(double minWidth, double maxWidth) { + double x =maxIntrinsicLineExtent(); + if(xmaxWidth) return maxWidth; + return x; +} + +TextPainter::TextPainter(std::shared_ptr& text, TextDirection textDirection): + textAlign_(TextAlign::start), + textDirection_(textDirection), + textScaler_(TextScaler::LinearTextScaler(1.0)), + text_(text) +{ +} + +void TextPainter::layout(double minWidth, double maxWidth) +{ + double layoutMaxWidth = maxWidth; + auto paragraph = _createParagraph(text_); + paragraph->layout(layoutMaxWidth); + + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================, TextPainter::layout, width = " << layoutMaxWidth; + + TextLayout layout(paragraph, textDirection_, plainText()); + double contentWidth = layout._contentWidthFor(minWidth, maxWidth); + layoutCache_ = std::make_shared(layout,0.0,layoutMaxWidth,contentWidth); + + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================, TextPainter::layout content width = " << contentWidth; + + //TODO: flutter/packages/flutter/lib/src/painting/text_painter.dart: 1192 +} + +double TextPainter::_computePaintOffsetFraction(TextAlign textAlign, TextDirection textDirection) +{ + if(textAlign==TextAlign::left) return 0.0; + if(textAlign==TextAlign::right) return 1.0; + if(textAlign==TextAlign::center) return 0.5; + if(textAlign==TextAlign::start || textAlign==TextAlign::justify) { + if (textDirection==TextDirection::ltr) return 0.0; + else if (textDirection==TextDirection::rtl) return 1.0; + } + if(textAlign==TextAlign::end) { + if (textDirection==TextDirection::ltr) return 1.0; + else if (textDirection==TextDirection::rtl) return 0.0; + } + return 0.0; +} + +Size TextPainter::size() const { + return Size(width(), height()); +} + +ParagraphStyle TextPainter::_createParagraphStyle(const std::optional &textAlignOverride) +{ + TextStyle baseStyle; + return baseStyle.getParagraphStyle( + textAlignOverride.has_value() ? textAlignOverride.value() : textAlign_, + textDirection_, + textScaler_ + ); +} + +fml::RefPtr TextPainter::_createParagraph(std::shared_ptr& text) +{ + auto style = _createParagraphStyle(); + auto builder = fml::MakeRefCounted(style.encoded()); + text->build(builder); + rebuildParagraphForPaint_=false; + return builder->build2(); +} + +void TextPainter::paint(fml::RefPtr canvas, Offset & offset) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================, TextPainter::paint::offset = " << offset.dx << "-" << offset.dy; + layoutCache_->layout.paragraph->paint(canvas.get(), offset.dx, offset.dy); +} + + +void PaintingContext::repaintCompositedChild(std::shared_ptr &child) { + auto childContex = PaintingContext{}; + Offset zero(0.0,0.0); + child->paint(childContex, zero); + childContex.picture_ = childContex.recorder_->endRecording2(); + child->rootLayer().picture = childContex.picture_; +} + +void PaintingContext::paintChild(std::shared_ptr& child, Offset &offset) { + child->paint(*this, offset); +} + +fml::RefPtr PaintingContext::getCanvas() { + if(canvas_) { + return canvas_; + } + recorder_ = fml::MakeRefCounted(); + auto rect = Rect::largest(); + + canvas_ = fml::MakeRefCounted(recorder_->BeginRecording( + SkRect::MakeLTRB(flutter::SafeNarrow(rect.left), + flutter::SafeNarrow(rect.top), + flutter::SafeNarrow(rect.right), + flutter::SafeNarrow(rect.bottom)))); + recorder_->set_canvas(canvas_); + return canvas_; +} + +BoxConstraints ViewConfiguration::physicalConstraints() const{ + Size physicalSize = view_->physicalSize(); + BoxConstraints physicalConstraints; + physicalConstraints.minWidth = physicalSize.width; + physicalConstraints.maxWidth = physicalSize.width; + physicalConstraints.minHeight = physicalSize.height; + physicalConstraints.maxHeight = physicalSize.height; + return physicalConstraints; +} + +BoxConstraints ViewConfiguration::logicalConstraints() const { + Size physicalSize = view_->physicalSize(); + BoxConstraints logicalConstraints; + double devicePixelRatio = view_->devicePixelRatio(); + + logicalConstraints.minWidth = physicalSize.width/devicePixelRatio; + logicalConstraints.maxWidth = physicalSize.width/devicePixelRatio; + logicalConstraints.minHeight = physicalSize.height/devicePixelRatio; + logicalConstraints.maxHeight = physicalSize.height/devicePixelRatio; + return logicalConstraints; +} + +double ViewConfiguration::devicePixelRatio() const { + return view_->devicePixelRatio(); +} + +fml::RefPtr TransformLayer::buildScene(fml::RefPtr builder){ + auto engineLayer = builder->pushTransform2(transform); + builder->addPicture(0.0, 0.0, picture.get(), 0); + builder->pop(); + auto scene = builder->build2(); + return scene; +} + +void RenderObject::scheduleInitialLayout() { + owner_->nodesNeedingLayout.push_back(shared_from_this()); +} + +void RenderObject::scheduleInitialPaint(TransformLayer &layer) { + rootLayer_ = layer; + owner_->nodesNeedingPaint.push_back(shared_from_this()); +} + +void RenderObject::layout(const BoxConstraints &constraints) { + constraints_ = constraints; + performLayout(); +} + +RenderParagraph::RenderParagraph(std::shared_ptr &text, TextDirection textDirection) + :textPainter_(text,textDirection) { +} + +void RenderParagraph::performLayout() { + _layoutTextWithConstraints(constraints_.loosen()); + size_ = textPainter_.size(); + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================, RenderParagraph::performLayout::size = " << size_.width << "-" << size_.height; +} + +void RenderParagraph::_layoutTextWithConstraints(BoxConstraints constraints) { + textPainter_.layout(constraints.minWidth, constraints.maxWidth); +} + +void RenderParagraph::paint(PaintingContext &context, Offset &offset) { + auto canvas = context.getCanvas(); + textPainter_.paint(canvas, offset); +} + +RenderPositionedBox::RenderPositionedBox(std::shared_ptr child) { + setChild(child); +} + +void RenderPositionedBox::performLayout() { + child_->layout(constraints_.loosen()); + size_ = Size(constraints_.maxWidth, constraints_.maxHeight); + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================, RenderPositionedBox::performLayout::size = " << size_.width << "-" << size_.height; +} + +void RenderPositionedBox::paint(PaintingContext &context, Offset &offset) +{ + auto cs = child_->size(); + double dx = size_.width - cs.width; + double dy = size_.height - cs.height; + Offset o(dx/2.0+offset.dx,dy/2.0+offset.dy); + context.paintChild(child_, o); +} + +RenderView::RenderView(std::shared_ptr &view):view_(view) +{ +} + +void RenderView::performLayout() { + child_->layout(configuration.logicalConstraints()); +} + +void RenderView::prepareInitialFrame() { + scheduleInitialLayout(); + auto layer = _updateMatricesAndCreateNewRootLayer(); + scheduleInitialPaint(layer); +} + +TransformLayer RenderView::_updateMatricesAndCreateNewRootLayer() { + rootTransform_ = SkM44( + flutter::SafeNarrow(configuration.devicePixelRatio()), flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), + flutter::SafeNarrow(0.0), flutter::SafeNarrow(configuration.devicePixelRatio()), flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), + flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), flutter::SafeNarrow(1.0), flutter::SafeNarrow(0.0), + flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), flutter::SafeNarrow(0.0), flutter::SafeNarrow(1.0) + ); + auto rootLayer = TransformLayer(rootTransform_); + rootLayer.owner = shared_from_this(); + return rootLayer; +} + +void RenderView::paint(PaintingContext &context, Offset &offset) +{ + context.paintChild(child_,offset); + rootLayer_.picture = context.picture(); +} + +void RenderView::compositeFrame() { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,RenderView::compositeFrame::SceneBuilder"; + fml::RefPtr sceneBuilder = fml::MakeRefCounted(); + auto scene = rootLayer_.buildScene(sceneBuilder); + view_->render(scene); +} + + +void PipelineOwner::flushLayout() { + for(auto & node : nodesNeedingLayout) { + node->_layoutWithoutResize(); + } +} + +void PipelineOwner::flushPaint() { + for(auto & node : nodesNeedingPaint) { + PaintingContext::repaintCompositedChild(node); + } +} + +void PipelineOwner::setRootNode(std::shared_ptr node) { + rootNode_ = node; + std::shared_ptr ptr = shared_from_this(); + node->attach(ptr); +} + +ViewRenderingFlutterBinding::ViewRenderingFlutterBinding(std::shared_ptr root): root_(root){ + rootPipelineOwner_=createRootPipelineOwner(); + auto flutterView = keels::PlatformDispatcher::instance().implicitView(); + auto renderView = initRenderView(flutterView); + renderView->setChild(root); + root_ = nullptr; +} + +std::shared_ptr ViewRenderingFlutterBinding::createRootPipelineOwner(){ + return std::make_shared(); +} + +std::shared_ptr ViewRenderingFlutterBinding::initRenderView(std::shared_ptr& view) { + auto renderView = std::make_shared(view); + rootPipelineOwner_->setRootNode(renderView); + addRenderView(renderView); + renderView->prepareInitialFrame(); + return renderView; +} + +ViewConfiguration ViewRenderingFlutterBinding::createViewConfigurationFor(std::shared_ptr &view) { + return ViewConfiguration(view->flutterView()); +} + +void ViewRenderingFlutterBinding::addRenderView(std::shared_ptr &view) { + int64_t id = view->flutterView()->viewId(); + view->configuration = createViewConfigurationFor(view); + viewIdToRenderView_[id]=view; +} + +void ViewRenderingFlutterBinding::scheduleFrame() { + ensureFrameCallbacksRegistered(); +} + +void ViewRenderingFlutterBinding::ensureFrameCallbacksRegistered() { + std::shared_ptr ptr = shared_from_this(); + auto draw_frame = fml::MakeCopyable([ptr](){ + ptr->handleDrawFrame(); + }); + PlatformDispatcher::instance().SetOnDrawFrame(draw_frame); +} + +void ViewRenderingFlutterBinding::handleDrawFrame() { + rootPipelineOwner_->flushLayout(); + rootPipelineOwner_->flushPaint(); + for(auto & view : viewIdToRenderView_) { + view.second->compositeFrame(); + } +} + +void Helloworld() { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << ",====================== run Helloworld ======================"; + std::shared_ptr text = std::make_shared(u"hello world"); + std::shared_ptr renderParagraph = std::make_shared(text, TextDirection::ltr); + std::shared_ptr renderPositionedBox = std::make_shared(renderParagraph); + std::shared_ptr view = std::make_shared(renderPositionedBox); + view->scheduleFrame(); +} + +} \ No newline at end of file diff --git a/lib/ui/helloworld.h b/lib/ui/helloworld.h new file mode 100644 index 0000000000..7f26315f25 --- /dev/null +++ b/lib/ui/helloworld.h @@ -0,0 +1,240 @@ +#ifndef KEELS_LIB_UI_HELLO_WORLD_H_ +#define KEELS_LIB_UI_HELLO_WORLD_H_ + +#include +#include "flutter/lib/ui/text.h" +#include "flutter/lib/ui/platform_dispatcher.h" +#include "flutter/lib/ui/text/paragraph_builder.h" +#include "flutter/lib/ui/painting/picture_recorder.h" +#include "flutter/lib/ui/painting/canvas.h" +#include "flutter/lib/ui/compositing/scene_builder.h" +#include "flutter/lib/ui/geometry.h" +#include + +namespace keels +{ + +const inline double kDefaultFontSize = 14.0; +class PipelineOwner; +class RenderObject; + +class InlineSpan { +public: + InlineSpan() = default; + virtual ~InlineSpan() = default; + virtual void build(fml::RefPtr builder) = 0; + virtual const std::u16string& toPlainText() const = 0; +}; + +class TextSpan : public InlineSpan{ +public: + TextSpan(const std::u16string& text); + std::u16string& text() {return text_;} + void build(fml::RefPtr builder) override; + const std::u16string& toPlainText() const override {return text_;} + +private: + std::u16string text_; +}; + +class TextScaler{ +public: + static const TextScaler LinearTextScaler(double factor){return TextScaler(factor);} + TextScaler(double factor):textScaleFactor_(factor){} + double scale(double fontSize) const { return fontSize*textScaleFactor_;} +private: + double textScaleFactor_; +}; + +class TextStyle{ +public: + ParagraphStyle getParagraphStyle(const TextAlign &textAlign, + const TextDirection &textDirection, + const TextScaler &textScaler); +}; + +struct TextLayout{ + TextLayout(const fml::RefPtr &p, + const TextDirection &w, + const std::u16string &r): paragraph(p),writingDirection(w),rawString(r) {} + double maxIntrinsicLineExtent() const {return paragraph->maxIntrinsicWidth();} + double _contentWidthFor(double minWidth, double maxWidth); + + fml::RefPtr paragraph; + TextDirection writingDirection; + std::u16string rawString; +}; + +struct TextPainterLayoutCacheWithOffset{ + TextPainterLayoutCacheWithOffset(const TextLayout&tl, double ta, double lm, double co): + layout(tl), textAlignment(ta),layoutMaxWidth(lm), contentWidth(co){} + Offset paintOffset() {return Offset(0.0,0.0);} + TextLayout layout; + double textAlignment; + double layoutMaxWidth; + double contentWidth; +}; + +class TextPainter { +public: + TextPainter(std::shared_ptr &text, TextDirection textDirection); + void layout(double minWidth, double maxWidth); + const std::u16string& plainText() const {return text_->toPlainText();} + void paint(fml::RefPtr canvas, Offset & offset); + double width() const {return layoutCache_->contentWidth;} + double height() const {return layoutCache_->layout.paragraph->height();} + Size size() const; +private: + ParagraphStyle _createParagraphStyle(const std::optional &textAlignOverride=std::nullopt); + fml::RefPtr _createParagraph(std::shared_ptr &text); + double _computePaintOffsetFraction(TextAlign textAlign, TextDirection textDirection); +private: + TextAlign textAlign_; + TextDirection textDirection_; + TextScaler textScaler_; + std::shared_ptr text_; + bool rebuildParagraphForPaint_; + std::shared_ptr layoutCache_; +}; + + +class PaintingContext { +public: + static void repaintCompositedChild(std::shared_ptr &child); + void paintChild(std::shared_ptr& child, Offset &offset); + fml::RefPtr getCanvas(); + fml::RefPtr picture() {return picture_;} +private: + fml::RefPtr canvas_ = nullptr; + fml::RefPtr recorder_ = nullptr; + fml::RefPtr picture_ = nullptr; +}; + +class BoxConstraints{ +public: + BoxConstraints(double minW=0, + double maxW=std::numeric_limits::infinity(), + double minH=0, + double maxH=std::numeric_limits::infinity()) + :minWidth(minW),maxWidth(maxW),minHeight(minH),maxHeight(maxH){} + BoxConstraints loosen() {return BoxConstraints(0,maxWidth,0,maxHeight);} + double minWidth; + double maxWidth; + double minHeight; + double maxHeight; +}; + +class ViewConfiguration{ +public: + ViewConfiguration(std::shared_ptr view=nullptr): view_(view){}; + BoxConstraints physicalConstraints() const; + BoxConstraints logicalConstraints() const; + double devicePixelRatio() const; +private: + std::shared_ptr view_; +}; + +class TransformLayer{ +public: + TransformLayer()=default; + TransformLayer(const SkM44 &t):transform(t){} + fml::RefPtr buildScene(fml::RefPtr builder); + SkM44 transform; + std::shared_ptr owner; + fml::RefPtr picture; +}; + +class RenderObject : public std::enable_shared_from_this{ +public: + RenderObject()=default; + virtual ~RenderObject()=default; + void layout(const BoxConstraints &constraints); + virtual void performLayout() = 0; + void _layoutWithoutResize() {performLayout();} + void attach(std::shared_ptr &owner) {owner_=owner;} + void setChild(std::shared_ptr child) {child_ = child;} + std::shared_ptr& child() {return child_;} + Size size() const {return size_;} + virtual void paint(PaintingContext &context, Offset &offset){context.paintChild(child_,offset);} + void scheduleInitialLayout(); + void scheduleInitialPaint(TransformLayer &layer); + TransformLayer& rootLayer() {return rootLayer_;} +protected: + BoxConstraints constraints_; + std::shared_ptr owner_; + std::shared_ptr child_; + Size size_; + TransformLayer rootLayer_; +}; + +class RenderParagraph : public RenderObject{ +public: + RenderParagraph(std::shared_ptr &text, TextDirection textDirection); + void performLayout() override; + void paint(PaintingContext &context, Offset &offset) override; +private: + void _layoutTextWithConstraints(BoxConstraints constraints); + TextPainter textPainter_; +}; + +class RenderPositionedBox : public RenderObject{ +public: + RenderPositionedBox(std::shared_ptr child); + void performLayout() override; + void paint(PaintingContext &context, Offset &offset) override; +}; + +class RenderView : public RenderObject{ +public: + RenderView(std::shared_ptr &view); + void performLayout() override; + std::shared_ptr& flutterView() {return view_;} + void prepareInitialFrame(); + ViewConfiguration configuration; + void paint(PaintingContext &context, Offset &offset) override; + void compositeFrame(); +private: + TransformLayer _updateMatricesAndCreateNewRootLayer(); +private: + SkM44 rootTransform_; + std::shared_ptr view_; +}; + +class PipelineOwner: public std::enable_shared_from_this { +public: + PipelineOwner()=default; + ~PipelineOwner()=default; + void flushLayout(); + void flushPaint(); + std::shared_ptr& rootNode() {return rootNode_;} + void setRootNode(std::shared_ptr node); + std::list> nodesNeedingLayout; + std::list> nodesNeedingPaint; +private: + std::shared_ptr rootNode_; //render view +}; + + +class ViewRenderingFlutterBinding: public std::enable_shared_from_this { +public: + ViewRenderingFlutterBinding(std::shared_ptr root); + std::shared_ptr createRootPipelineOwner(); + std::shared_ptr initRenderView(std::shared_ptr& view); + ViewConfiguration createViewConfigurationFor(std::shared_ptr &view); + void addRenderView(std::shared_ptr &); + void scheduleFrame(); + void ensureFrameCallbacksRegistered(); + void handleDrawFrame(); +private: + std::shared_ptr root_; + std::shared_ptr rootPipelineOwner_; + std::unordered_map> viewIdToRenderView_; +}; + +void Helloworld(); + +} + + + +#endif \ No newline at end of file diff --git a/lib/ui/painting/picture_recorder.cc b/lib/ui/painting/picture_recorder.cc index 58d9d86632..32571ac535 100644 --- a/lib/ui/painting/picture_recorder.cc +++ b/lib/ui/painting/picture_recorder.cc @@ -31,6 +31,22 @@ sk_sp PictureRecorder::BeginRecording(SkRect bounds) { return display_list_builder_; } +fml::RefPtr PictureRecorder::endRecording2() { + if (!canvas_) { + return nullptr; + } + + auto display_list = display_list_builder_->Build(); + display_list_builder_ = nullptr; + + FML_DCHECK(display_list->has_rtree()); + auto canvas_picture = fml::MakeRefCounted(std::move(display_list)); + canvas_->Invalidate(); + canvas_ = nullptr; + FML_LOG(ERROR) << __FILE__ << ":" <<__LINE__ << ":" << std::this_thread::get_id() << "================,PictureRecorder::endRecording2"; + return canvas_picture; +} + void PictureRecorder::endRecording(Dart_Handle dart_picture) { if (!canvas_) { return; diff --git a/lib/ui/painting/picture_recorder.h b/lib/ui/painting/picture_recorder.h index ccbc8d030e..d449829977 100644 --- a/lib/ui/painting/picture_recorder.h +++ b/lib/ui/painting/picture_recorder.h @@ -23,6 +23,7 @@ class PictureRecorder : public RefCountedDartWrappable { sk_sp BeginRecording(SkRect bounds); void endRecording(Dart_Handle dart_picture); + fml::RefPtr endRecording2(); void set_canvas(fml::RefPtr canvas) { canvas_ = std::move(canvas); } diff --git a/lib/ui/platform_dispatcher.cc b/lib/ui/platform_dispatcher.cc new file mode 100644 index 0000000000..6b837a395a --- /dev/null +++ b/lib/ui/platform_dispatcher.cc @@ -0,0 +1,42 @@ +#include "flutter/lib/ui/platform_dispatcher.h" +#include "flutter/lib/ui/window.h" + +namespace keels{ + +PlatformDispatcher::PlatformDispatcher() { + //TODO missed +} + +PlatformDispatcher& PlatformDispatcher::instance() { + static std::unique_ptr inst = std::unique_ptr(new PlatformDispatcher); + return *inst; +} + +void PlatformDispatcher::AddView(const int64_t view_id, const flutter::ViewportMetrics& view_metrics) { + if (views_.find(view_id) == views_.end()) { + auto ptr = std::make_shared(view_id, *this, view_metrics); + views_[view_id] = std::move(ptr); + //TODO, _invoke(onMetricsChanged, _onMetricsChangedZone); + } +} + +void PlatformDispatcher::UpdateViewMetrics(const int64_t view_id, const flutter::ViewportMetrics& view_metrics) { + auto it = views_.find(view_id); + if (it != views_.end()) { + it->second->view_metrics()=view_metrics; + //TODO, _invoke(onMetricsChanged, _onMetricsChangedZone); + } +} + +std::shared_ptr PlatformDispatcher::implicitView() { + auto it = views_.find(GetImplicitViewId()); + if(it!=views_.end()){ + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,implicitView()" + << "width=" << it->second->physicalSize().width; + return it->second; + } + return nullptr; +} + + +} \ No newline at end of file diff --git a/lib/ui/platform_dispatcher.h b/lib/ui/platform_dispatcher.h new file mode 100644 index 0000000000..f36240b33b --- /dev/null +++ b/lib/ui/platform_dispatcher.h @@ -0,0 +1,46 @@ +#ifndef KEELS_LIB_UI_PLATFORM_DISPATCHER_H_ +#define KEELS_LIB_UI_PLATFORM_DISPATCHER_H_ + +#include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/common/constants.h" +#include "flutter/lib/ui/window.h" +namespace keels{ + +class PlatformDispatcher{ +private: + PlatformDispatcher(); + +public: + ~PlatformDispatcher()=default; + static PlatformDispatcher& instance(); + + std::shared_ptr implicitView(); + + void SetPlatformConfiguration(flutter::PlatformConfiguration* config) {config_ = config;} + flutter::PlatformConfiguration* GetPlatformConfiguration() {return config_;} + + void SetOnBeginFrame(const std::function& fn) {on_begin_frame_ = fn;} + const std::function& GetOnBeginFrame() {return on_begin_frame_;} + + void SetOnDrawFrame(const std::function& fn) {on_draw_frame_ = fn;} + const std::function& GetOnDrawFrame() {return on_draw_frame_;} + + void SetOnUpdateFrameData(const std::function& fn) {on_update_frame_data_ = fn;} + const std::function& GetOnUpdateFrameData() {return on_update_frame_data_;} + + void AddView(const int64_t view_id, const flutter::ViewportMetrics& view_metrics); + void UpdateViewMetrics(const int64_t view_id, const flutter::ViewportMetrics& view_metrics); + + int64_t GetImplicitViewId() const {return flutter::kFlutterImplicitViewId;} + +private: + flutter::PlatformConfiguration* config_ = nullptr; + std::function on_begin_frame_; + std::function on_draw_frame_; + std::function on_update_frame_data_; + std::unordered_map> views_; +}; + +} + +#endif \ No newline at end of file diff --git a/lib/ui/text.cc b/lib/ui/text.cc new file mode 100644 index 0000000000..ec6de7eb2e --- /dev/null +++ b/lib/ui/text.cc @@ -0,0 +1,45 @@ +#include "flutter/lib/ui/text.h" + +namespace keels{ + + +//TODO +ParagraphStyle::ParagraphStyle(const std::optional& textAlign, + const std::optional& textDirection, + const std::optional& fontSize) + :encoded_(encodeParagraphStyle(textAlign,textDirection,fontSize)), + fontSize_(fontSize), + leadingDistribution_(TextLeadingDistribution::proportional) + {} + +//TODO +std::vector ParagraphStyle::encodeParagraphStyle( + const std::optional& textAlign, + const std::optional& textDirection, + const std::optional& fontSize) { + std::vector result; + result.resize(7,0); + + if (textAlign.has_value()) { + result[0] |= 1 << 1; + result[1] = static_cast(textAlign.value()); + } + + if(textDirection.has_value()) { + result[0] |= 1 << 2; + result[2] = static_cast(textDirection.value()); + } + + if (fontSize.has_value()) { + result[0] |= 1 << 8; + } + + return result; +} + +NativeParagraphBuilder::NativeParagraphBuilder(const ParagraphStyle &style) + :defaultLeadingDistribution_(style.leadingDistribution()) +{} + + +} \ No newline at end of file diff --git a/lib/ui/text.h b/lib/ui/text.h new file mode 100644 index 0000000000..c78bcbf611 --- /dev/null +++ b/lib/ui/text.h @@ -0,0 +1,66 @@ +#ifndef KEELS_LIB_UI_TEXT_H_ +#define KEELS_LIB_UI_TEXT_H_ + +#include +#include + +namespace keels{ + +enum class TextDirection:int32_t { + rtl, + ltr +}; + +enum class TextLeadingDistribution:int32_t { + proportional, + even +}; + +enum class TextAlign { + left, + right, + center, + justify, + start, + end +}; + +class ParagraphConstraints { +public: + ParagraphConstraints(double w):width(w){} + double width; +}; + +class ParagraphStyle { +public: + ParagraphStyle(const std::optional& textAlign, + const std::optional& textDirection, + const std::optional& fontSize); + + const std::vector& encoded() const { return encoded_;} + TextLeadingDistribution leadingDistribution() const { return leadingDistribution_;} + +private: + std::vector encodeParagraphStyle(const std::optional& textAlign, + const std::optional& textDirection, + const std::optional& fontSize); + +private: + std::vector encoded_; + std::optional fontSize_; + TextLeadingDistribution leadingDistribution_; +}; + +// dart:ParagraphBuilder +class NativeParagraphBuilder { +public: + NativeParagraphBuilder(const ParagraphStyle &style); +private: + TextLeadingDistribution defaultLeadingDistribution_; + int placeholderCount_ = 0; + std::vector placeholderScales_ = std::vector{}; +}; + +} + +#endif \ No newline at end of file diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index c79c09110b..2110b45516 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -26,6 +26,7 @@ #include "third_party/tonic/dart_binding_macros.h" #include "third_party/tonic/dart_library_natives.h" #include "third_party/tonic/typed_data/dart_byte_data.h" +#include "flutter/lib/ui/platform_dispatcher.h" namespace flutter { namespace { @@ -222,6 +223,30 @@ void decodeStrut(Dart_Handle strut_data, } } +ParagraphBuilder::ParagraphBuilder(const std::vector& encoded) { + int32_t mask = 0; + txt::ParagraphStyle style; + { + mask = encoded[0]; + + if (mask & kPSTextDirectionMask) { + style.text_direction = + static_cast(encoded[kPSTextDirectionIndex]); + } + } + + auto cfg = keels::PlatformDispatcher::instance().GetPlatformConfiguration(); + FontCollection& font_collection = cfg->client()->GetFontCollection(); + + //TODO + auto impeller_enabled = true; + auto font = font_collection.GetFontCollection(); + + m_paragraph_builder_ = txt::ParagraphBuilder::CreateSkiaBuilder( + style, font, impeller_enabled); + +} + ParagraphBuilder::ParagraphBuilder( Dart_Handle encoded_data, Dart_Handle strutData, @@ -496,6 +521,24 @@ void ParagraphBuilder::pop() { m_paragraph_builder_->Pop(); } +//TODO, return error code +int32_t ParagraphBuilder::addText2(const std::u16string& text) { + if(text.empty()){ + return 0; + } + const UChar* text_ptr = reinterpret_cast(text.data()); + UErrorCode error_code = U_ZERO_ERROR; + u_strToUTF8(nullptr, 0, nullptr, text_ptr, text.size(), &error_code); + if (error_code != U_BUFFER_OVERFLOW_ERROR) { + return -1; + } + + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,ParagraphBuilder::addText2"; + + m_paragraph_builder_->AddText(text); + return 0; +} + Dart_Handle ParagraphBuilder::addText(const std::u16string& text) { if (text.empty()) { return Dart_Null(); @@ -528,6 +571,13 @@ void ParagraphBuilder::addPlaceholder(double width, m_paragraph_builder_->AddPlaceholder(placeholder_run); } +fml::RefPtr ParagraphBuilder::build2() { + auto paragraph = fml::MakeRefCounted(m_paragraph_builder_->Build()); + m_paragraph_builder_.reset(); + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,ParagraphBuilder::build2"; + return paragraph; +} + void ParagraphBuilder::build(Dart_Handle paragraph_handle) { Paragraph::Create(paragraph_handle, m_paragraph_builder_->Build()); m_paragraph_builder_.reset(); diff --git a/lib/ui/text/paragraph_builder.h b/lib/ui/text/paragraph_builder.h index 809f91bc3f..18cda67478 100644 --- a/lib/ui/text/paragraph_builder.h +++ b/lib/ui/text/paragraph_builder.h @@ -52,6 +52,8 @@ class ParagraphBuilder : public RefCountedDartWrappable { void pop(); + int32_t addText2(const std::u16string& text); + Dart_Handle addText(const std::u16string& text); // Pushes the information required to leave an open space, where Flutter may @@ -66,9 +68,11 @@ class ParagraphBuilder : public RefCountedDartWrappable { double baseline_offset, unsigned baseline); + fml::RefPtr build2(); void build(Dart_Handle paragraph_handle); private: + explicit ParagraphBuilder(const std::vector& encoded); explicit ParagraphBuilder(Dart_Handle encoded, Dart_Handle strutData, const std::string& fontFamily, diff --git a/lib/ui/window.cc b/lib/ui/window.cc new file mode 100644 index 0000000000..6562dee15c --- /dev/null +++ b/lib/ui/window.cc @@ -0,0 +1,16 @@ +#include "flutter/lib/ui/window.h" +#include "flutter/lib/ui/platform_dispatcher.h" + +namespace keels { +FlutterView::FlutterView(int64_t view_id, PlatformDispatcher& platform_dispatcher,const flutter::ViewportMetrics& view_metrics): + view_id_(view_id), platform_dispatcher_(platform_dispatcher), view_metrics_(view_metrics){} + +void FlutterView::render(fml::RefPtr scene, std::optional size) { + auto cfg = platform_dispatcher_.GetPlatformConfiguration(); + double width = size.has_value() ? size.value().width : view_metrics_.physical_width; + double height = size.has_value() ? size.value().height : view_metrics_.physical_height; + cfg->client()->Render(view_id_, scene.get(), width, height); + +} + +} \ No newline at end of file diff --git a/lib/ui/window.h b/lib/ui/window.h new file mode 100644 index 0000000000..175552fcaa --- /dev/null +++ b/lib/ui/window.h @@ -0,0 +1,28 @@ +#ifndef KEELS_LIB_UI_WINDOW_H_ +#define KEELS_LIB_UI_WINDOW_H_ + +#include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/lib/ui/geometry.h" +#include "flutter/lib/ui/compositing/scene.h" + +//dart file: flutter/bin/cache/pkg/sky_engine/lib/ui/window.dart + +namespace keels{ +class PlatformDispatcher; +class FlutterView{ +public: + FlutterView(int64_t view_id, PlatformDispatcher& platform_dispatcher,const flutter::ViewportMetrics& view_metrics); + double devicePixelRatio() const { return view_metrics_.device_pixel_ratio;} + Size physicalSize() const {return Size(view_metrics_.physical_width, view_metrics_.physical_height);} + flutter::ViewportMetrics& view_metrics() {return view_metrics_;} + int64_t viewId()const {return view_id_;} + void render(fml::RefPtr scene, std::optional size=std::nullopt); +private: + int64_t view_id_; + PlatformDispatcher& platform_dispatcher_; + flutter::ViewportMetrics view_metrics_; +}; +} + + +#endif \ No newline at end of file diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc index 965ca85f4f..bbb636dd5d 100644 --- a/lib/ui/window/platform_configuration.cc +++ b/lib/ui/window/platform_configuration.cc @@ -3,8 +3,11 @@ // found in the LICENSE file. #include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/lib/ui/platform_dispatcher.h" #include +#include +#include #include "flutter/common/constants.h" #include "flutter/fml/trace_event.h" @@ -88,40 +91,11 @@ void PlatformConfiguration::DidCreateIsolate() { void PlatformConfiguration::AddView(int64_t view_id, const ViewportMetrics& view_metrics) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,PlatformConfiguration::AddView"; auto [view_iterator, insertion_happened] = metrics_.emplace(view_id, view_metrics); FML_DCHECK(insertion_happened); - - std::shared_ptr dart_state = add_view_.dart_state().lock(); - if (!dart_state) { - return; - } - tonic::DartState::Scope scope(dart_state); - tonic::CheckAndHandleError(tonic::DartInvoke( - add_view_.Get(), - { - tonic::ToDart(view_id), - tonic::ToDart(view_metrics.device_pixel_ratio), - tonic::ToDart(view_metrics.physical_width), - tonic::ToDart(view_metrics.physical_height), - tonic::ToDart(view_metrics.physical_padding_top), - tonic::ToDart(view_metrics.physical_padding_right), - tonic::ToDart(view_metrics.physical_padding_bottom), - tonic::ToDart(view_metrics.physical_padding_left), - tonic::ToDart(view_metrics.physical_view_inset_top), - tonic::ToDart(view_metrics.physical_view_inset_right), - tonic::ToDart(view_metrics.physical_view_inset_bottom), - tonic::ToDart(view_metrics.physical_view_inset_left), - tonic::ToDart(view_metrics.physical_system_gesture_inset_top), - tonic::ToDart(view_metrics.physical_system_gesture_inset_right), - tonic::ToDart(view_metrics.physical_system_gesture_inset_bottom), - tonic::ToDart(view_metrics.physical_system_gesture_inset_left), - tonic::ToDart(view_metrics.physical_touch_slop), - tonic::ToDart(view_metrics.physical_display_features_bounds), - tonic::ToDart(view_metrics.physical_display_features_type), - tonic::ToDart(view_metrics.physical_display_features_state), - tonic::ToDart(view_metrics.display_id), - })); + keels::PlatformDispatcher::instance().AddView(view_id, view_metrics); } bool PlatformConfiguration::RemoveView(int64_t view_id) { @@ -151,44 +125,15 @@ bool PlatformConfiguration::RemoveView(int64_t view_id) { bool PlatformConfiguration::UpdateViewMetrics( int64_t view_id, const ViewportMetrics& view_metrics) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,PlatformConfiguration::UpdateViewMetrics"; auto found_iter = metrics_.find(view_id); if (found_iter == metrics_.end()) { return false; } found_iter->second = view_metrics; - - std::shared_ptr dart_state = - update_window_metrics_.dart_state().lock(); - if (!dart_state) { - return false; - } - tonic::DartState::Scope scope(dart_state); - tonic::CheckAndHandleError(tonic::DartInvoke( - update_window_metrics_.Get(), - { - tonic::ToDart(view_id), - tonic::ToDart(view_metrics.device_pixel_ratio), - tonic::ToDart(view_metrics.physical_width), - tonic::ToDart(view_metrics.physical_height), - tonic::ToDart(view_metrics.physical_padding_top), - tonic::ToDart(view_metrics.physical_padding_right), - tonic::ToDart(view_metrics.physical_padding_bottom), - tonic::ToDart(view_metrics.physical_padding_left), - tonic::ToDart(view_metrics.physical_view_inset_top), - tonic::ToDart(view_metrics.physical_view_inset_right), - tonic::ToDart(view_metrics.physical_view_inset_bottom), - tonic::ToDart(view_metrics.physical_view_inset_left), - tonic::ToDart(view_metrics.physical_system_gesture_inset_top), - tonic::ToDart(view_metrics.physical_system_gesture_inset_right), - tonic::ToDart(view_metrics.physical_system_gesture_inset_bottom), - tonic::ToDart(view_metrics.physical_system_gesture_inset_left), - tonic::ToDart(view_metrics.physical_touch_slop), - tonic::ToDart(view_metrics.physical_display_features_bounds), - tonic::ToDart(view_metrics.physical_display_features_type), - tonic::ToDart(view_metrics.physical_display_features_state), - tonic::ToDart(view_metrics.display_id), - })); + keels::PlatformDispatcher::instance().UpdateViewMetrics(view_id, view_metrics); + return true; } @@ -370,26 +315,24 @@ void PlatformConfiguration::DispatchSemanticsAction(int32_t node_id, void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime, uint64_t frame_number) { TRACE_EVENT0("flutter", "PlatformConfiguration::BeginFrame"); - std::shared_ptr dart_state = - begin_frame_.dart_state().lock(); - if (!dart_state) { - return; - } - tonic::DartState::Scope scope(dart_state); int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds(); TRACE_EVENT0("flutter", "PlatformConfiguration::begin_frame_"); - tonic::CheckAndHandleError( - tonic::DartInvoke(begin_frame_.Get(), { - Dart_NewInteger(microseconds), - Dart_NewInteger(frame_number), - })); - - UIDartState::Current()->FlushMicrotasksNow(); + auto &begin_frame = keels::PlatformDispatcher::instance().GetOnBeginFrame(); + auto &update_frame_date = keels::PlatformDispatcher::instance().GetOnUpdateFrameData(); + if(begin_frame) { + begin_frame(microseconds); + } + if(update_frame_date) { + update_frame_date(microseconds); + } TRACE_EVENT0("flutter", "PlatformConfiguration::draw_frame_"); - tonic::CheckAndHandleError(tonic::DartInvokeVoid(draw_frame_.Get())); + auto &draw_frame = keels::PlatformDispatcher::instance().GetOnDrawFrame(); + if(draw_frame) { + draw_frame(); + } } void PlatformConfiguration::ReportTimings(std::vector timings) { diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index d591070c12..bc7b5663e5 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -52,6 +52,8 @@ source_set("dart_plugin_registrant") { source_set("runtime") { sources = [ + "capsule.cc", + "capsule.h", "dart_isolate.cc", "dart_isolate.h", "dart_isolate_group_data.cc", diff --git a/runtime/capsule.cc b/runtime/capsule.cc new file mode 100644 index 0000000000..770faaf031 --- /dev/null +++ b/runtime/capsule.cc @@ -0,0 +1,25 @@ +#include "flutter/runtime/capsule.h" +#include +#include + +namespace keels{ + +std::weak_ptr Capsule::CreateRunningCapsule( + const flutter::Settings& settings, + std::unique_ptr platform_configuration, + const fml::closure& capsule_create_callback) { + + auto ptr = std::make_unique>(std::make_shared()); + auto raw = ptr.get(); + ptr.release(); + (*raw)->platform_configuration_ = std::move(platform_configuration); + if(capsule_create_callback) { + capsule_create_callback(); + } + + + return (*raw)->GetWeakPtr(); +} + + +} \ No newline at end of file diff --git a/runtime/capsule.h b/runtime/capsule.h new file mode 100644 index 0000000000..654e623133 --- /dev/null +++ b/runtime/capsule.h @@ -0,0 +1,47 @@ +#ifndef KEELS_RUNTIME_CAPSULE_H_ +#define KEELS_RUNTIME_CAPSULE_H_ + +#include +#include +#include +#include +#include + +#include "flutter/common/task_runners.h" +#include "flutter/fml/compiler_specific.h" +#include "flutter/fml/macros.h" +#include "flutter/fml/mapping.h" +#include "flutter/lib/ui/io_manager.h" +#include "flutter/lib/ui/snapshot_delegate.h" +#include "flutter/lib/ui/window/platform_configuration.h" +#include "flutter/runtime/dart_isolate.h" + +namespace keels{ + +class Capsule :public std::enable_shared_from_this { + +public: + static std::weak_ptr CreateRunningCapsule ( + const flutter::Settings& settings, + std::unique_ptr platform_configuration, + const fml::closure& capsule_create_callback + ); + + std::weak_ptr GetWeakPtr() { + std::shared_ptr ptr = shared_from_this(); + return ptr; + } + + flutter::PlatformConfiguration* platform_configuration() const { + return platform_configuration_.get(); + } + +private: + std::unique_ptr platform_configuration_; + + +}; + +} + +#endif \ No newline at end of file diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc index b967b9cde9..8f4911c6eb 100644 --- a/runtime/runtime_controller.cc +++ b/runtime/runtime_controller.cc @@ -3,8 +3,11 @@ // found in the LICENSE file. #include "flutter/runtime/runtime_controller.h" +#include "flutter/runtime/capsule.h" #include +#include +#include #include "flutter/common/constants.h" #include "flutter/common/settings.h" @@ -19,6 +22,17 @@ #include "flutter/runtime/runtime_delegate.h" #include "third_party/tonic/dart_message_handler.h" +#include "flutter/fml/make_copyable.h" +#include "flutter/lib/ui/text.h" +#include "flutter/lib/ui/platform_dispatcher.h" +#include "flutter/lib/ui/text/paragraph_builder.h" +#include "flutter/lib/ui/painting/picture_recorder.h" +#include "flutter/lib/ui/painting/canvas.h" +#include "flutter/lib/ui/compositing/scene_builder.h" +#include "flutter/lib/ui/geometry.h" +// #include "flutter/lib/ui/floating_point.h" +#include "flutter/lib/ui/helloworld.h" + namespace flutter { RuntimeController::RuntimeController(RuntimeDelegate& p_client, @@ -138,6 +152,8 @@ bool RuntimeController::FlushRuntimeStateToIsolate() { bool RuntimeController::AddView(int64_t view_id, const ViewportMetrics& view_metrics) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << "================================== AddView ==================" + << "width=" << view_metrics.physical_width; platform_data_.viewport_metrics_for_views[view_id] = view_metrics; if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { platform_configuration->AddView(view_id, view_metrics); @@ -159,6 +175,9 @@ bool RuntimeController::RemoveView(int64_t view_id) { bool RuntimeController::SetViewportMetrics(int64_t view_id, const ViewportMetrics& metrics) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << "================================== SetViewportMetrics ==================" + << "width=" << metrics.physical_width; + TRACE_EVENT0("flutter", "SetViewportMetrics"); platform_data_.viewport_metrics_for_views[view_id] = metrics; @@ -331,8 +350,8 @@ bool RuntimeController::DispatchSemanticsAction(int32_t node_id, PlatformConfiguration* RuntimeController::GetPlatformConfigurationIfAvailable() { - std::shared_ptr root_isolate = root_isolate_.lock(); - return root_isolate ? root_isolate->platform_configuration() : nullptr; + auto ptr = root_capsule_.lock(); + return ptr ? ptr->platform_configuration() : nullptr; } // |PlatformConfigurationClient| @@ -355,7 +374,7 @@ void RuntimeController::Render(int64_t view_id, double width, double height) { const ViewportMetrics* view_metrics = - UIDartState::Current()->platform_configuration()->GetMetrics(view_id); + keels::PlatformDispatcher::instance().GetPlatformConfiguration()->GetMetrics(view_id); if (view_metrics == nullptr) { return; } @@ -454,6 +473,34 @@ tonic::DartErrorHandleType RuntimeController::GetLastError() { return root_isolate ? root_isolate->GetLastError() : tonic::kNoError; } +bool RuntimeController::LaunchCapsule( + const Settings& settings, + const fml::closure& create_callback) { + auto ptr = keels::Capsule::CreateRunningCapsule(settings, std::make_unique(this),create_callback); + + if(ptr.lock()) { + root_capsule_ = ptr; + } + + if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) { + keels::PlatformDispatcher::instance().SetPlatformConfiguration(platform_configuration); + if (!FlushRuntimeStateToIsolate()) { + FML_DLOG(ERROR) << "Could not set up initial isolate state."; + } + } else { + FML_DCHECK(false) << "RuntimeController created without window binding."; + } + + FML_LOG(ERROR) << "================================= run capsule main ==================="; + + auto view = keels::PlatformDispatcher::instance().implicitView(); + context_.task_runners.GetUITaskRunner()->PostTask(fml::MakeCopyable([]()mutable{ + keels::Helloworld(); + })); + + return true; +} + bool RuntimeController::LaunchRootIsolate( const Settings& settings, const fml::closure& root_isolate_create_callback, diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h index cb1618f9d3..a7866808f3 100644 --- a/runtime/runtime_controller.h +++ b/runtime/runtime_controller.h @@ -25,6 +25,7 @@ #include "flutter/runtime/platform_isolate_manager.h" #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" +#include "flutter/runtime/capsule.h" namespace flutter { @@ -158,6 +159,10 @@ class RuntimeController : public PlatformConfigurationClient { const std::vector& dart_entrypoint_args, std::unique_ptr isolate_configuration); + [[nodiscard]] bool LaunchCapsule( + const Settings& settings, + const fml::closure& create_callback); + //---------------------------------------------------------------------------- /// @brief Clone the runtime controller. Launching an isolate with a /// cloned runtime controller will use the same snapshots and @@ -649,6 +654,7 @@ class RuntimeController : public PlatformConfigurationClient { fml::RefPtr isolate_snapshot_; std::function idle_notification_callback_; PlatformData platform_data_; + std::weak_ptr root_capsule_; std::weak_ptr root_isolate_; std::weak_ptr spawning_isolate_; std::optional root_isolate_return_code_; diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 0555fcf4df..e90d96dadf 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -238,6 +238,7 @@ void Animator::DrawLastLayerTrees( } void Animator::RequestFrame(bool regenerate_layer_trees) { + FML_LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":" << std::this_thread::get_id() << "================,Animator::RequestFrame" << std::endl; TRACE_EVENT0("flutter", "Animator::RequestFrame"); if (regenerate_layer_trees) { // This event will be closed by BeginFrame. BeginFrame will only be called diff --git a/shell/common/engine.cc b/shell/common/engine.cc index c4081ad891..c132c27b86 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include "flutter/common/settings.h" #include "flutter/fml/make_copyable.h" @@ -179,7 +181,7 @@ bool Engine::UpdateAssetManager( *asset_manager_ == *new_asset_manager) { return false; } - + asset_manager_ = new_asset_manager; if (!asset_manager_) { @@ -210,6 +212,30 @@ bool Engine::Restart(RunConfiguration configuration) { return Run(std::move(configuration)) == Engine::RunStatus::Success; } +Engine::RunStatus Engine::RunCapsule(RunConfiguration configuration) { + if (!configuration.IsValid()) { + FML_LOG(ERROR) << "Engine run configuration was invalid."; + return RunStatus::Failure; + } + + UpdateAssetManager(configuration.GetAssetManager()); + + FML_LOG(ERROR) << __FILE__ << ":" <<__LINE__ << ":" << std::this_thread::get_id() << "======================================== Engine::RunCapsule ================================="; + + auto capsule_create_callback = [&]() { + FML_LOG(ERROR) << __FILE__ << ":" <<__LINE__ << ":" << std::this_thread::get_id() << ",============== capsule call back"; + if (settings_.prefetched_default_font_manager) { + SetupDefaultFontManager(); + } + }; + + if (!runtime_controller_->LaunchCapsule(settings_, capsule_create_callback)) { + return RunStatus::Failure; + } + + return RunStatus::Success; +} + Engine::RunStatus Engine::Run(RunConfiguration configuration) { if (!configuration.IsValid()) { FML_LOG(ERROR) << "Engine run configuration was invalid."; diff --git a/shell/common/engine.h b/shell/common/engine.h index 65660f6124..9dbf4720cf 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -460,6 +460,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// [[nodiscard]] RunStatus Run(RunConfiguration configuration); + [[nodiscard]] RunStatus RunCapsule(RunConfiguration configuration); + //---------------------------------------------------------------------------- /// @brief Tears down an existing root isolate, reuses the components of /// that isolate and attempts to launch a new isolate using the diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 5c0d22f37c..a320531834 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -685,7 +685,7 @@ void Shell::RunEngine( result(Engine::RunStatus::Failure); return; } - auto run_result = weak_engine->Run(std::move(run_configuration)); + auto run_result = weak_engine->RunCapsule(std::move(run_configuration)); if (run_result == flutter::Engine::RunStatus::Failure) { FML_LOG(ERROR) << "Could not launch engine with configuration."; } -- Gitee