From 9f8b9bb96d5698b6a5bcbe8e9e042318b255875f Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Tue, 19 May 2015 14:20:04 -0700 Subject: [PATCH] Teach SkyView path to draw a circle This CL adds a global view object that can receive a Picture and be signaled to draw. When using SkyView, this Picture shows up on screen. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/1134913003 --- engine/bindings/builtin_sky.cc | 6 ++++ engine/bindings/builtin_sky.h | 2 ++ .../scripts/templates/dart_blink.template | 2 ++ engine/core/core.gni | 3 ++ engine/core/painting/Canvas.cpp | 2 +- engine/core/painting/Picture.h | 1 + engine/core/script/dart_controller.cc | 7 ++++ engine/core/script/dart_controller.h | 2 ++ engine/core/view/View.cpp | 29 +++++++++++++++ engine/core/view/View.h | 36 +++++++++++++++++++ engine/core/view/View.idl | 9 +++++ engine/public/sky/BUILD.gn | 3 ++ engine/public/sky/sky_view.cc | 26 ++++++++++++-- engine/public/sky/sky_view.h | 14 ++++++-- engine/public/sky/sky_view_client.cc | 13 +++++++ engine/public/sky/sky_view_client.h | 20 +++++++++++ examples/raw/hello_world.dart | 21 ++++++++++- shell/ui/engine.cc | 13 ++++++- shell/ui/engine.h | 7 +++- 19 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 engine/core/view/View.cpp create mode 100644 engine/core/view/View.h create mode 100644 engine/core/view/View.idl create mode 100644 engine/public/sky/sky_view_client.cc create mode 100644 engine/public/sky/sky_view_client.h diff --git a/engine/bindings/builtin_sky.cc b/engine/bindings/builtin_sky.cc index 8546f762d..00d7ee8f8 100644 --- a/engine/bindings/builtin_sky.cc +++ b/engine/bindings/builtin_sky.cc @@ -8,6 +8,7 @@ #include "sky/engine/bindings/builtin.h" #include "sky/engine/core/frame/LocalDOMWindow.h" #include "sky/engine/core/script/dom_dart_state.h" +#include "sky/engine/core/view/View.h" #include "sky/engine/tonic/dart_error.h" namespace blink { @@ -27,6 +28,11 @@ void BuiltinSky::InstallWindow(DOMDartState* dart_state) { // TODO(abarth): Retain the document wrapper. } +void BuiltinSky::InstallView(View* view) { + CHECK(!LogIfError( + Dart_SetField(library_.value(), ToDart("view"), ToDart(view)))); +} + Dart_Handle BuiltinSky::GetClassByName(const char* class_name) { Dart_Handle name_handle = ToDart(class_name); Dart_Handle class_handle = Dart_GetType(library_.value(), name_handle, 0, nullptr); diff --git a/engine/bindings/builtin_sky.h b/engine/bindings/builtin_sky.h index 1fd207892..cbeb54c89 100644 --- a/engine/bindings/builtin_sky.h +++ b/engine/bindings/builtin_sky.h @@ -12,6 +12,7 @@ namespace blink { class DOMDartState; +class View; class BuiltinSky : public DartClassProvider { public: @@ -19,6 +20,7 @@ class BuiltinSky : public DartClassProvider { ~BuiltinSky(); void InstallWindow(DOMDartState* dart_state); + void InstallView(View* view); // DartClassProvider: Dart_Handle GetClassByName(const char* class_name) override; diff --git a/engine/bindings/scripts/templates/dart_blink.template b/engine/bindings/scripts/templates/dart_blink.template index 29558a248..694b00ba7 100644 --- a/engine/bindings/scripts/templates/dart_blink.template +++ b/engine/bindings/scripts/templates/dart_blink.template @@ -18,4 +18,6 @@ part '{{callback.name}}.dart'; Window window; Document get document => window.document; +View view; + typedef EventListener(Event event); diff --git a/engine/core/core.gni b/engine/core/core.gni index 51547c81d..69751a6e9 100644 --- a/engine/core/core.gni +++ b/engine/core/core.gni @@ -1026,6 +1026,8 @@ sky_core_files = [ "script/dom_dart_state.cc", "script/dom_dart_state.h", "script/monitor.h", + "view/View.cpp", + "view/View.h", ] core_idl_files = get_path_info([ @@ -1107,6 +1109,7 @@ core_idl_files = get_path_info([ "painting/PaintingContext.idl", "painting/Picture.idl", "painting/PictureRecorder.idl", + "view/View.idl", ], "abspath") diff --git a/engine/core/painting/Canvas.cpp b/engine/core/painting/Canvas.cpp index f169066c1..e14493d48 100644 --- a/engine/core/painting/Canvas.cpp +++ b/engine/core/painting/Canvas.cpp @@ -117,7 +117,7 @@ void Canvas::drawPicture(Picture* picture) return; ASSERT(picture); ASSERT(m_displayList->isRecording()); - m_canvas->drawPicture(picture->displayList()->picture()); + m_canvas->drawPicture(picture->toSkia()); } void Canvas::drawPaint(const Paint* paint) diff --git a/engine/core/painting/Picture.h b/engine/core/painting/Picture.h index adfc90856..f01e069f5 100644 --- a/engine/core/painting/Picture.h +++ b/engine/core/painting/Picture.h @@ -18,6 +18,7 @@ public: ~Picture() override; static PassRefPtr create(PassRefPtr); + SkPicture* toSkia() const { return m_displayList->picture(); } DisplayList* displayList() const { return m_displayList.get(); } private: diff --git a/engine/core/script/dart_controller.cc b/engine/core/script/dart_controller.cc index f927ebb6e..22fe4d38f 100644 --- a/engine/core/script/dart_controller.cc +++ b/engine/core/script/dart_controller.cc @@ -348,6 +348,13 @@ void DartController::CreateIsolateFor(PassOwnPtr state, Dart_ExitIsolate(); } +void DartController::InstallView(View* view) { + DartIsolateScope isolate_scope(dart_state()->isolate()); + DartApiScope dart_api_scope; + + builtin_sky_->InstallView(view); +} + void DartController::ClearForClose() { // Don't use a DartIsolateScope here since we never exit the isolate. Dart_EnterIsolate(dom_dart_state_->isolate()); diff --git a/engine/core/script/dart_controller.h b/engine/core/script/dart_controller.h index 5e2717ec5..270aabd06 100644 --- a/engine/core/script/dart_controller.h +++ b/engine/core/script/dart_controller.h @@ -20,6 +20,7 @@ class DOMDartState; class DartValue; class HTMLScriptElement; class KURL; +class View; class DartController { public: @@ -44,6 +45,7 @@ class DartController { void ClearForClose(); void CreateIsolateFor(PassOwnPtr dom_dart_state, const KURL& url); + void InstallView(View* view); DOMDartState* dart_state() const { return dom_dart_state_.get(); } diff --git a/engine/core/view/View.cpp b/engine/core/view/View.cpp new file mode 100644 index 000000000..03cb986f3 --- /dev/null +++ b/engine/core/view/View.cpp @@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium 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 "sky/engine/config.h" +#include "sky/engine/core/view/View.h" + +namespace blink { + +PassRefPtr View::create(const base::Closure& schedulePaintCallback) +{ + return adoptRef(new View(schedulePaintCallback)); +} + +View::View(const base::Closure& schedulePaintCallback) + : m_schedulePaintCallback(schedulePaintCallback) +{ +} + +View::~View() +{ +} + +void View::schedulePaint() +{ + m_schedulePaintCallback.Run(); +} + +} // namespace blink diff --git a/engine/core/view/View.h b/engine/core/view/View.h new file mode 100644 index 000000000..756874c3b --- /dev/null +++ b/engine/core/view/View.h @@ -0,0 +1,36 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_CORE_VIEW_VIEW_H_ +#define SKY_ENGINE_CORE_VIEW_VIEW_H_ + +#include "base/callback.h" +#include "sky/engine/core/painting/Picture.h" +#include "sky/engine/tonic/dart_wrappable.h" +#include "sky/engine/wtf/PassRefPtr.h" +#include "sky/engine/wtf/RefCounted.h" + +namespace blink { + +class View : public RefCounted, public DartWrappable { + DEFINE_WRAPPERTYPEINFO(); +public: + ~View() override; + static PassRefPtr create(const base::Closure& schedulePaintCallback); + + Picture* picture() const { return m_picture.get(); } + void setPicture(Picture* picture) { m_picture = picture; } + + void schedulePaint(); + +private: + explicit View(const base::Closure& schedulePaintCallback); + + base::Closure m_schedulePaintCallback; + RefPtr m_picture; +}; + +} // namespace blink + +#endif // SKY_ENGINE_CORE_VIEW_VIEW_H_ diff --git a/engine/core/view/View.idl b/engine/core/view/View.idl new file mode 100644 index 000000000..abfe81f87 --- /dev/null +++ b/engine/core/view/View.idl @@ -0,0 +1,9 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +interface View { + attribute Picture picture; + + void schedulePaint(); +}; diff --git a/engine/public/sky/BUILD.gn b/engine/public/sky/BUILD.gn index 872d2d3d8..7ad7a523c 100644 --- a/engine/public/sky/BUILD.gn +++ b/engine/public/sky/BUILD.gn @@ -4,6 +4,7 @@ source_set("sky") { deps = [ + "//base", "//skia", "//sky/engine/core", "//sky/engine/platform", @@ -19,5 +20,7 @@ source_set("sky") { "sky_display_metrics.h", "sky_view.cc", "sky_view.h", + "sky_view_client.cc", + "sky_view_client.h", ] } diff --git a/engine/public/sky/sky_view.cc b/engine/public/sky/sky_view.cc index aa9776647..e9a6bdbd0 100644 --- a/engine/public/sky/sky_view.cc +++ b/engine/public/sky/sky_view.cc @@ -5,17 +5,27 @@ #include "config.h" #include "sky/engine/public/sky/sky_view.h" +#include "base/bind.h" #include "sky/engine/core/script/dart_controller.h" #include "sky/engine/core/script/dom_dart_state.h" +#include "sky/engine/core/view/View.h" #include "sky/engine/platform/weborigin/KURL.h" +#include "sky/engine/public/sky/sky_view_client.h" namespace blink { -std::unique_ptr SkyView::Create() { - return std::unique_ptr(new SkyView); +struct SkyView::Data { + RefPtr view_; +}; + +std::unique_ptr SkyView::Create(SkyViewClient* client) { + return std::unique_ptr(new SkyView(client)); } -SkyView::SkyView() { +SkyView::SkyView(SkyViewClient* client) + : client_(client), + data_(new Data), + weak_factory_(this) { } SkyView::~SkyView() { @@ -29,12 +39,18 @@ void SkyView::SetDisplayMetrics(const SkyDisplayMetrics& metrics) { } void SkyView::Load(const WebURL& url) { + data_->view_ = View::create(base::Bind( + &SkyView::SchedulePaint, weak_factory_.GetWeakPtr())); + dart_controller_.reset(new DartController); dart_controller_->CreateIsolateFor(adoptPtr(new DOMDartState(nullptr)), url); + dart_controller_->InstallView(data_->view_.get()); dart_controller_->LoadMainLibrary(url); } skia::RefPtr SkyView::Paint() { + if (Picture* picture = data_->view_->picture()) + return skia::SharePtr(picture->toSkia()); return skia::RefPtr(); } @@ -42,4 +58,8 @@ bool SkyView::HandleInputEvent(const WebInputEvent& event) { return false; } +void SkyView::SchedulePaint() { + client_->SchedulePaint(); +} + } // namespace blink diff --git a/engine/public/sky/sky_view.h b/engine/public/sky/sky_view.h index 8a2860a00..a8d722260 100644 --- a/engine/public/sky/sky_view.h +++ b/engine/public/sky/sky_view.h @@ -6,6 +6,7 @@ #define SKY_ENGINE_PUBLIC_SKY_SKY_VIEW_H_ #include +#include "base/memory/weak_ptr.h" #include "skia/ext/refptr.h" #include "sky/engine/public/platform/WebCommon.h" #include "sky/engine/public/platform/WebURL.h" @@ -14,11 +15,12 @@ namespace blink { class DartController; +class SkyViewClient; class WebInputEvent; class SkyView { public: - static std::unique_ptr Create(); + static std::unique_ptr Create(SkyViewClient* client); ~SkyView(); void SetDisplayMetrics(const SkyDisplayMetrics& metrics); @@ -27,9 +29,17 @@ class SkyView { bool HandleInputEvent(const WebInputEvent& event); private: - SkyView(); + explicit SkyView(SkyViewClient* client); + void SchedulePaint(); + + class Data; + + SkyViewClient* client_; std::unique_ptr dart_controller_; + std::unique_ptr data_; + + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(SkyView); }; diff --git a/engine/public/sky/sky_view_client.cc b/engine/public/sky/sky_view_client.cc new file mode 100644 index 000000000..488eaf173 --- /dev/null +++ b/engine/public/sky/sky_view_client.cc @@ -0,0 +1,13 @@ +// Copyright 2015 The Chromium 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 "config.h" +#include "sky/engine/public/sky/sky_view_client.h" + +namespace blink { + +SkyViewClient::~SkyViewClient() { +} + +} // namespace blink diff --git a/engine/public/sky/sky_view_client.h b/engine/public/sky/sky_view_client.h new file mode 100644 index 000000000..16f9552b4 --- /dev/null +++ b/engine/public/sky/sky_view_client.h @@ -0,0 +1,20 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SKY_ENGINE_PUBLIC_SKY_SKY_VIEW_CLIENT_H_ +#define SKY_ENGINE_PUBLIC_SKY_SKY_VIEW_CLIENT_H_ + +namespace blink { + +class SkyViewClient { + public: + virtual void SchedulePaint() = 0; + + protected: + virtual ~SkyViewClient(); +}; + +} // namespace blink + +#endif // SKY_ENGINE_PUBLIC_SKY_SKY_VIEW_CLIENT_H_ diff --git a/examples/raw/hello_world.dart b/examples/raw/hello_world.dart index cbf03f078..52cfc50c4 100644 --- a/examples/raw/hello_world.dart +++ b/examples/raw/hello_world.dart @@ -2,6 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import "dart:math"; +import 'dart:sky'; + void main() { - print("Hello, world"); + print("Hello, world"); + + double width = 500.0; + double height = 500.0; + + PictureRecorder recorder = new PictureRecorder(width, height); + double radius = min(width, height) * 0.45; + + Paint paint = new Paint()..setARGB(255, 0, 255, 0); + + recorder.drawCircle(width / 2, height / 2, radius, paint); + + print("Storing picture"); + view.picture = recorder.endRecording(); + + print("Scheduling paint"); + view.schedulePaint(); } diff --git a/shell/ui/engine.cc b/shell/ui/engine.cc index 058682ded..e11463880 100644 --- a/shell/ui/engine.cc +++ b/shell/ui/engine.cc @@ -85,6 +85,13 @@ skia::RefPtr Engine::Paint() { physical_size_.width(), physical_size_.height(), &factory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag)); + if (sky_view_) { + skia::RefPtr picture = sky_view_->Paint(); + canvas->clear(SK_ColorBLACK); + if (picture) + canvas->drawPicture(picture.get()); + } + if (web_view_) web_view_->paint(canvas.get(), blink::WebRect(gfx::Rect(physical_size_))); @@ -149,7 +156,7 @@ void Engine::OnInputEvent(InputEventPtr event) { void Engine::LoadURL(const mojo::String& url) { // Enable SkyView here. if (false) { - sky_view_ = blink::SkyView::Create(); + sky_view_ = blink::SkyView::Create(this); sky_view_->Load(GURL(url)); return; } @@ -182,6 +189,10 @@ void Engine::didCreateIsolate(blink::WebLocalFrame* frame, CreateServiceProvider(config_.service_provider_context)); } +void Engine::SchedulePaint() { + animator_->RequestFrame(); +} + blink::ServiceProvider* Engine::services() { return this; } diff --git a/shell/ui/engine.h b/shell/ui/engine.h index e10781a21..5311229d7 100644 --- a/shell/ui/engine.h +++ b/shell/ui/engine.h @@ -16,6 +16,7 @@ #include "skia/ext/refptr.h" #include "sky/engine/public/platform/ServiceProvider.h" #include "sky/engine/public/sky/sky_view.h" +#include "sky/engine/public/sky/sky_view_client.h" #include "sky/engine/public/web/WebFrameClient.h" #include "sky/engine/public/web/WebViewClient.h" #include "sky/shell/gpu_delegate.h" @@ -34,7 +35,8 @@ class Engine : public UIDelegate, public blink::ServiceProvider, public mojo::NavigatorHost, public blink::WebFrameClient, - public blink::WebViewClient { + public blink::WebViewClient, + public blink::SkyViewClient { public: struct Config { ServiceProviderContext* service_provider_context; @@ -75,6 +77,9 @@ class Engine : public UIDelegate, void didCreateIsolate(blink::WebLocalFrame* frame, Dart_Isolate isolate) override; + // SkyViewClient methods: + void SchedulePaint() override; + // Services methods: mojo::NavigatorHost* NavigatorHost() override; -- GitLab