Kevin Gu
4 年前
当前提交
b1009c12
共有 87 个文件被更改,包括 8146 次插入 和 424 次删除
-
2com.unity.uiwidgets/.editorconfig
-
56com.unity.uiwidgets/Runtime/ui/geometry.cs
-
8com.unity.uiwidgets/Runtime/ui/painting/painting.cs
-
56engine/Build.bee.cs
-
2engine/src/common/settings.h
-
2engine/src/flow/embedded_views.h
-
433engine/src/lib/ui/painting/canvas.cc
-
83engine/src/lib/ui/painting/canvas.h
-
2engine/src/lib/ui/painting/image_encoding.cc
-
49engine/src/lib/ui/painting/picture.cc
-
8engine/src/lib/ui/painting/picture.h
-
19engine/src/lib/ui/painting/picture_recorder.cc
-
13engine/src/lib/ui/window/platform_message.cc
-
3engine/src/lib/ui/window/platform_message.h
-
415engine/src/lib/ui/window/window.cc
-
72engine/src/lib/ui/window/window.h
-
2engine/src/render_api_d3d11.cc
-
25engine/src/runtime/mono_api.cc
-
8engine/src/runtime/mono_api.h
-
8engine/src/runtime/mono_isolate.cc
-
2engine/src/runtime/mono_isolate.h
-
42engine/src/shell/common/animator.cc
-
6engine/src/shell/common/animator.h
-
194com.unity.uiwidgets/Runtime/ui/painting/native_bindings.cs
-
3com.unity.uiwidgets/Runtime/ui/painting/native_bindings.cs.meta
-
277com.unity.uiwidgets/Runtime/ui2/compositing.cs
-
3com.unity.uiwidgets/Runtime/ui2/compositing.cs.meta
-
154com.unity.uiwidgets/Runtime/ui2/hooks.cs
-
3com.unity.uiwidgets/Runtime/ui2/hooks.cs.meta
-
62com.unity.uiwidgets/Runtime/ui2/isolate.cs
-
64com.unity.uiwidgets/Runtime/ui2/native_bindings.cs
-
1001com.unity.uiwidgets/Runtime/ui2/painting.cs
-
310com.unity.uiwidgets/Runtime/ui2/window.cs
-
3com.unity.uiwidgets/Runtime/ui2/window.cs.meta
-
39engine/src/lib/ui/painting/color_filter.cc
-
30engine/src/lib/ui/painting/color_filter.h
-
12engine/src/lib/ui/painting/engine_layer.cc
-
27engine/src/lib/ui/painting/engine_layer.h
-
109engine/src/lib/ui/painting/gradient.cc
-
45engine/src/lib/ui/painting/gradient.h
-
37engine/src/lib/ui/painting/image_filter.cc
-
29engine/src/lib/ui/painting/image_filter.h
-
26engine/src/lib/ui/painting/image_shader.cc
-
26engine/src/lib/ui/painting/image_shader.h
-
27engine/src/lib/ui/painting/matrix.cc
-
9engine/src/lib/ui/painting/matrix.h
-
150engine/src/lib/ui/painting/paint.cc
-
20engine/src/lib/ui/painting/paint.h
-
353engine/src/lib/ui/painting/path.cc
-
71engine/src/lib/ui/painting/path.h
-
21engine/src/lib/ui/painting/rrect.cc
-
14engine/src/lib/ui/painting/rrect.h
-
9engine/src/lib/ui/painting/shader.cc
-
28engine/src/lib/ui/painting/shader.h
-
89engine/src/lib/ui/painting/vertices.cc
-
30engine/src/lib/ui/painting/vertices.h
-
12engine/src/lib/ui/window/pointer_data.cc
-
83engine/src/lib/ui/window/pointer_data.h
-
19engine/src/lib/ui/window/pointer_data_packet.cc
-
27engine/src/lib/ui/window/pointer_data_packet.h
-
281engine/src/lib/ui/window/pointer_data_packet_converter.cc
-
50engine/src/lib/ui/window/pointer_data_packet_converter.h
-
68engine/src/lib/ui/window/viewport_metrics.cc
-
79engine/src/lib/ui/window/viewport_metrics.h
-
270engine/src/runtime/runtime_controller.cc
-
123engine/src/runtime/runtime_controller.h
-
7engine/src/runtime/runtime_delegate.cc
-
30engine/src/runtime/runtime_delegate.h
-
8engine/src/runtime/window_data.cc
-
27engine/src/runtime/window_data.h
-
502engine/src/shell/common/engine.cc
-
149engine/src/shell/common/engine.h
-
119engine/src/shell/common/platform_view.cc
-
80engine/src/shell/common/platform_view.h
-
57engine/src/shell/common/pointer_data_dispatcher.cc
-
72engine/src/shell/common/pointer_data_dispatcher.h
-
1001engine/src/shell/common/shell.cc
-
525engine/src/shell/common/shell.h
-
64engine/src/lib/ui/compositing/scene.cc
-
39engine/src/lib/ui/compositing/scene.h
-
202engine/src/lib/ui/compositing/scene_builder.cc
-
85engine/src/lib/ui/compositing/scene_builder.h
-
0/com.unity.uiwidgets/Runtime/ui2/isolate.cs.meta
-
0/com.unity.uiwidgets/Runtime/ui2/native_bindings.cs.meta
-
0/com.unity.uiwidgets/Runtime/ui2/painting.cs.meta
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
#include <unordered_map> |
|||
#include <vector> |
|||
|
|||
#include "flutter/fml/time/time_point.h" |
|||
#include "include/gpu/GrContext.h" |
|||
#include "lib/ui/window/platform_message.h" |
|||
#include "lib/ui/window/pointer_data_packet.h" |
|||
#include "lib/ui/window/viewport_metrics.h" |
|||
#include "runtime/mono_api.h" |
|||
#include "runtime/mono_state.h" |
|||
|
|||
class FontCollection; |
|||
class Scene; |
|||
|
|||
enum class AccessibilityFeatureFlag : int32_t { |
|||
kAccessibleNavigation = 1 << 0, |
|||
kInvertColors = 1 << 1, |
|||
kDisableAnimations = 1 << 2, |
|||
kBoldText = 1 << 3, |
|||
kReduceMotion = 1 << 4, |
|||
kHighContrast = 1 << 5, |
|||
}; |
|||
|
|||
class WindowClient { |
|||
public: |
|||
virtual std::string DefaultRouteName() = 0; |
|||
virtual void ScheduleFrame() = 0; |
|||
virtual void Render(Scene* scene) = 0; |
|||
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) = 0; |
|||
virtual FontCollection& GetFontCollection() = 0; |
|||
virtual void SetNeedsReportTimings(bool value) = 0; |
|||
|
|||
protected: |
|||
virtual ~WindowClient(); |
|||
}; |
|||
public: |
|||
explicit Window(WindowClient* client); |
|||
|
|||
~Window(); |
|||
|
|||
WindowClient* client() const { return client_; } |
|||
|
|||
const ViewportMetrics& viewport_metrics() { return viewport_metrics_; } |
|||
|
|||
Mono_Handle mono_window() const { return mono_window_; } |
|||
|
|||
void DidCreateIsolate(); |
|||
void UpdateWindowMetrics(const ViewportMetrics& metrics); |
|||
void UpdateLocales(const std::vector<std::string>& locales); |
|||
void UpdateUserSettingsData(const std::string& data); |
|||
void UpdateLifecycleState(const std::string& data); |
|||
void UpdateAccessibilityFeatures(int32_t flags); |
|||
void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
void DispatchPointerDataPacket(const PointerDataPacket& packet); |
|||
void BeginFrame(fml::TimePoint frameTime); |
|||
void ReportTimings(std::vector<int64_t> timings); |
|||
|
|||
void CompletePlatformMessageResponse(int response_id, |
|||
std::vector<uint8_t> data); |
|||
void CompletePlatformMessageEmptyResponse(int response_id); |
|||
|
|||
private: |
|||
WindowClient* client_; |
|||
ViewportMetrics viewport_metrics_; |
|||
Mono_Handle mono_window_; |
|||
std::weak_ptr<MonoState> mono_state_; |
|||
|
|||
// We use id 0 to mean that no response is expected. |
|||
int next_response_id_ = 1; |
|||
std::unordered_map<int, fml::RefPtr<PlatformMessageResponse>> |
|||
pending_responses_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.ui { |
|||
class NativeBindings { |
|||
#if (UNITY_IOS || UNITY_TVOS || UNITY_WEBGL) && !UNITY_EDITOR
|
|||
const string dllName = "__Internal"; |
|||
#else
|
|||
const string dllName = "libUIWidgets_d"; |
|||
#endif
|
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr ImageShader_constructor(); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void ImageShader_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void ImageShader_initWithImage(IntPtr ptr, |
|||
IntPtr image, int tmx, int tmy, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr Gradient_constructor(); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Gradient_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void Gradient_initLinear(IntPtr ptr, |
|||
float* endPoints, int endPointsLength, |
|||
uint* colors, int colorsLength, |
|||
float* colorStops, int colorStopsLength, |
|||
int tileMode, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void Gradient_initRadial(IntPtr ptr, |
|||
float centerX, float centerY, float radius, |
|||
uint* colors, int colorsLength, |
|||
float* colorStops, int colorStopsLength, |
|||
int tileMode, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void Gradient_initConical(IntPtr ptr, |
|||
float startX, float startY, float startRadius, |
|||
float endX, float endY, float endRadius, |
|||
uint* colors, int colorsLength, |
|||
float* colorStops, int colorStopsLength, |
|||
int tileMode, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void Gradient_initSweep(IntPtr ptr, |
|||
float centerX, float centerY, |
|||
uint* colors, int colorsLength, |
|||
float* colorStops, int colorStopsLength, |
|||
int tileMode, float startAngle, float endAngle, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr ColorFilter_constructor(); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void ColorFilter_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void ColorFilter_initMode(IntPtr ptr, uint color, int blendMode); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void ColorFilter_initMatrix(IntPtr ptr, float* matrix4); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void ColorFilter_initLinearToSrgbGamma(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void ColorFilter_initSrgbToLinearGamma(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr ImageFilter_constructor(); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void ImageFilter_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void ImageFilter_initBlur(IntPtr ptr, float sigmaX, float sigmaY); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern unsafe void ImageFilter_initMatrix(IntPtr ptr, float* matrix4, int filterQuality); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr Canvas_constructor(IntPtr recorder, |
|||
double left, |
|||
double top, |
|||
double right, |
|||
double bottom); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Canvas_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Canvas_save(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Canvas_restore(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Image_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern int Image_width(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern int Image_height(IntPtr ptr); |
|||
|
|||
public delegate void Image_toByteDataCallback(IntPtr callbackHandle, IntPtr data, int length); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern string Image_toByteData(IntPtr ptr, int format, Image_toByteDataCallback callback, |
|||
IntPtr callbackHandle); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void Picture_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern int Picture_GetAllocationSize(IntPtr ptr); |
|||
|
|||
public delegate void Picture_toImageCallback(IntPtr callbackHandle, IntPtr result); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern string Picture_toImage(IntPtr ptr, int width, int height, Picture_toImageCallback callback, |
|||
IntPtr callbackHandle); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr PictureRecorder_constructor(); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern void PictureRecorder_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern bool PictureRecorder_isRecording(IntPtr ptr); |
|||
|
|||
[DllImport(dllName)] |
|||
public static extern IntPtr PictureRecorder_endRecording(IntPtr ptr); |
|||
} |
|||
|
|||
public abstract class NativeWrapper { |
|||
protected internal IntPtr _ptr { get; protected set; } |
|||
|
|||
protected NativeWrapper() { |
|||
} |
|||
|
|||
protected NativeWrapper(IntPtr ptr) { |
|||
D.assert(this._ptr != IntPtr.Zero); |
|||
this._ptr = ptr; |
|||
} |
|||
|
|||
~NativeWrapper() { |
|||
if (this._ptr != IntPtr.Zero) { |
|||
this.DisposePtr(this._ptr); |
|||
this._ptr = IntPtr.Zero; |
|||
} |
|||
} |
|||
|
|||
protected abstract void DisposePtr(IntPtr ptr); |
|||
} |
|||
|
|||
public abstract class NativeWrapperDisposable : IDisposable { |
|||
protected internal IntPtr _ptr { get; protected set; } |
|||
|
|||
protected NativeWrapperDisposable() { |
|||
} |
|||
|
|||
protected NativeWrapperDisposable(IntPtr ptr) { |
|||
D.assert(this._ptr != IntPtr.Zero); |
|||
this._ptr = ptr; |
|||
} |
|||
|
|||
~NativeWrapperDisposable() { |
|||
if (this._ptr != IntPtr.Zero) { |
|||
this.DisposePtr(this._ptr); |
|||
this._ptr = IntPtr.Zero; |
|||
} |
|||
} |
|||
|
|||
protected abstract void DisposePtr(IntPtr ptr); |
|||
|
|||
public void Dispose() { |
|||
if (this._ptr != IntPtr.Zero) { |
|||
this.DisposePtr(this._ptr); |
|||
this._ptr = IntPtr.Zero; |
|||
} |
|||
|
|||
GC.SuppressFinalize(this); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 334fd474090a463f811ef61d03d38e9e |
|||
timeCreated: 1595569910 |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Runtime.InteropServices; |
|||
using AOT; |
|||
using RSG; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.ui2 { |
|||
public class Scene : NativeWrapperDisposable { |
|||
internal Scene(IntPtr ptr) : base(ptr) { |
|||
} |
|||
|
|||
protected override void DisposePtr(IntPtr ptr) { |
|||
Scene_dispose(ptr); |
|||
} |
|||
|
|||
public Promise<Image> toImage(int width, int height) { |
|||
if (width <= 0 || height <= 0) { |
|||
throw new Exception("Invalid image dimensions."); |
|||
} |
|||
|
|||
var completer = new Promise<Image>(true); |
|||
GCHandle completerHandle = GCHandle.Alloc(completer); |
|||
|
|||
IntPtr error = |
|||
Scene_toImage(_ptr, width, height, _toImageCallback, |
|||
(IntPtr) completerHandle); |
|||
if (error != null) { |
|||
completerHandle.Free(); |
|||
throw new Exception(Marshal.PtrToStringAnsi(error)); |
|||
} |
|||
|
|||
return completer; |
|||
} |
|||
|
|||
[MonoPInvokeCallback(typeof(Scene_toImageCallback))] |
|||
static void _toImageCallback(IntPtr callbackHandle, IntPtr result) { |
|||
GCHandle completerHandle = (GCHandle) callbackHandle; |
|||
var completer = (Promise<Image>) completerHandle.Target; |
|||
completerHandle.Free(); |
|||
|
|||
if (result == IntPtr.Zero) { |
|||
completer.Reject(new Exception("operation failed")); |
|||
} |
|||
else { |
|||
var image = new Image(result); |
|||
completer.Resolve(image); |
|||
} |
|||
} |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Scene_dispose(IntPtr ptr); |
|||
|
|||
delegate void Scene_toImageCallback(IntPtr callbackHandle, IntPtr result); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr Scene_toImage(IntPtr ptr, int width, int height, Scene_toImageCallback callback, |
|||
IntPtr callbackHandle); |
|||
} |
|||
|
|||
public abstract class _EngineLayerWrapper : EngineLayer { |
|||
protected _EngineLayerWrapper(IntPtr ptr) : base(ptr) { |
|||
} |
|||
|
|||
internal List<_EngineLayerWrapper> _debugChildren; |
|||
|
|||
internal bool _debugWasUsedAsOldLayer = false; |
|||
|
|||
internal bool _debugCheckNotUsedAsOldLayer() { |
|||
D.assert( |
|||
!_debugWasUsedAsOldLayer, |
|||
() => "Layer $runtimeType was previously used as oldLayer.\n" + |
|||
"Once a layer is used as oldLayer, it may not be used again. Instead, " + |
|||
"after calling one of the SceneBuilder.push* methods and passing an oldLayer " + |
|||
"to it, use the layer returned by the method as oldLayer in subsequent " + |
|||
"frames."); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
public class TransformEngineLayer : _EngineLayerWrapper { |
|||
internal TransformEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class OffsetEngineLayer : _EngineLayerWrapper { |
|||
internal OffsetEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ClipRectEngineLayer : _EngineLayerWrapper { |
|||
internal ClipRectEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ClipRRectEngineLayer : _EngineLayerWrapper { |
|||
internal ClipRRectEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ClipPathEngineLayer : _EngineLayerWrapper { |
|||
internal ClipPathEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class OpacityEngineLayer : _EngineLayerWrapper { |
|||
internal OpacityEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ColorFilterEngineLayer : _EngineLayerWrapper { |
|||
internal ColorFilterEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ImageFilterEngineLayer : _EngineLayerWrapper { |
|||
internal ImageFilterEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class BackdropFilterEngineLayer : _EngineLayerWrapper { |
|||
internal BackdropFilterEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class ShaderMaskEngineLayer : _EngineLayerWrapper { |
|||
internal ShaderMaskEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class PhysicalShapeEngineLayer : _EngineLayerWrapper { |
|||
internal PhysicalShapeEngineLayer(IntPtr ptr) : base(ptr) { |
|||
} |
|||
} |
|||
|
|||
public class SceneBuilder : NativeWrapper { |
|||
public SceneBuilder() : base(SceneBuilder_constructor()) { |
|||
} |
|||
|
|||
protected override void DisposePtr(IntPtr ptr) { |
|||
SceneBuilder_dispose(ptr); |
|||
} |
|||
|
|||
readonly Dictionary<EngineLayer, string> _usedLayers = new Dictionary<EngineLayer, string>(); |
|||
|
|||
bool _debugCheckUsedOnce(EngineLayer layer, string usage) { |
|||
D.assert(() => { |
|||
if (layer == null) { |
|||
return true; |
|||
} |
|||
|
|||
D.assert( |
|||
!_usedLayers.ContainsKey(layer), |
|||
() => $"Layer {layer.GetType()} already used.\n" + |
|||
$"The layer is already being used as {_usedLayers[layer]} in this scene.\n" + |
|||
"A layer may only be used once in a given scene."); |
|||
|
|||
_usedLayers[layer] = usage; |
|||
return true; |
|||
}); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool _debugCheckCanBeUsedAsOldLayer(_EngineLayerWrapper layer, String methodName) { |
|||
D.assert(() => { |
|||
if (layer == null) { |
|||
return true; |
|||
} |
|||
|
|||
layer._debugCheckNotUsedAsOldLayer(); |
|||
D.assert(_debugCheckUsedOnce(layer, $"oldLayer in {methodName}")); |
|||
layer._debugWasUsedAsOldLayer = true; |
|||
return true; |
|||
}); |
|||
return true; |
|||
} |
|||
|
|||
readonly List<_EngineLayerWrapper> _layerStack = new List<_EngineLayerWrapper>(); |
|||
|
|||
bool _debugPushLayer(_EngineLayerWrapper newLayer) { |
|||
D.assert(() => { |
|||
if (_layerStack.isNotEmpty()) { |
|||
_EngineLayerWrapper currentLayer = _layerStack.last(); |
|||
currentLayer._debugChildren ??= new List<_EngineLayerWrapper>(); |
|||
currentLayer._debugChildren.Add(newLayer); |
|||
} |
|||
|
|||
_layerStack.Add(newLayer); |
|||
return true; |
|||
}); |
|||
return true; |
|||
} |
|||
|
|||
public unsafe TransformEngineLayer pushTransform( |
|||
float[] matrix4, |
|||
TransformEngineLayer oldLayer = null |
|||
) { |
|||
D.assert(PaintingUtils._matrix4IsValid(matrix4)); |
|||
D.assert(_debugCheckCanBeUsedAsOldLayer(oldLayer, "pushTransform")); |
|||
fixed (float* matrix4Ptr = matrix4) { |
|||
TransformEngineLayer layer = new TransformEngineLayer(SceneBuilder_pushTransform(_ptr, matrix4Ptr)); |
|||
D.assert(_debugPushLayer(layer)); |
|||
return layer; |
|||
} |
|||
} |
|||
|
|||
public OffsetEngineLayer pushOffset( |
|||
float dx, |
|||
float dy, |
|||
OffsetEngineLayer oldLayer = null |
|||
) { |
|||
D.assert(_debugCheckCanBeUsedAsOldLayer(oldLayer, "pushOffset")); |
|||
OffsetEngineLayer layer = new OffsetEngineLayer(SceneBuilder_pushOffset(_ptr, dx, dy)); |
|||
D.assert(_debugPushLayer(layer)); |
|||
return layer; |
|||
} |
|||
|
|||
public void pop() { |
|||
if (_layerStack.isNotEmpty()) { |
|||
_layerStack.removeLast(); |
|||
} |
|||
|
|||
SceneBuilder_pop(_ptr); |
|||
} |
|||
|
|||
public Scene build() { |
|||
return new Scene(SceneBuilder_build(_ptr)); |
|||
} |
|||
|
|||
public void addRetained(EngineLayer retainedLayer) { |
|||
D.assert(retainedLayer is _EngineLayerWrapper); |
|||
D.assert(() => { |
|||
_EngineLayerWrapper layer = retainedLayer as _EngineLayerWrapper; |
|||
|
|||
void recursivelyCheckChildrenUsedOnce(_EngineLayerWrapper parentLayer) { |
|||
_debugCheckUsedOnce(parentLayer, "retained layer"); |
|||
parentLayer._debugCheckNotUsedAsOldLayer(); |
|||
|
|||
if (parentLayer._debugChildren == null || parentLayer._debugChildren.isEmpty()) { |
|||
return; |
|||
} |
|||
|
|||
parentLayer._debugChildren.ForEach(recursivelyCheckChildrenUsedOnce); |
|||
} |
|||
|
|||
recursivelyCheckChildrenUsedOnce(layer); |
|||
|
|||
return true; |
|||
}); |
|||
|
|||
_EngineLayerWrapper wrapper = retainedLayer as _EngineLayerWrapper; |
|||
SceneBuilder_addRetained(_ptr, wrapper._ptr); |
|||
} |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr SceneBuilder_constructor(); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void SceneBuilder_dispose(IntPtr ptr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern unsafe IntPtr SceneBuilder_pushTransform(IntPtr ptr, float* matrix4); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr SceneBuilder_pushOffset(IntPtr ptr, float dx, float dy); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void SceneBuilder_pop(IntPtr ptr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr SceneBuilder_build(IntPtr ptr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void SceneBuilder_addRetained(IntPtr ptr, IntPtr retainedLayer); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 28c3db1a7c1746ca8d7725c27f41cb30 |
|||
timeCreated: 1597124223 |
|
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using AOT; |
|||
using Unity.UIWidgets.ui; |
|||
using UnityEngine; |
|||
|
|||
namespace Unity.UIWidgets.ui2 { |
|||
public static class Hooks { |
|||
public static void hook() { |
|||
Mono_hook( |
|||
Mono_throwException, |
|||
Mono_timelineGetMicros); |
|||
|
|||
Window_hook( |
|||
Window_constructor, |
|||
Window_dispose, |
|||
Window_updateWindowMetrics, |
|||
Window_beginFrame, |
|||
Window_drawFrame); |
|||
} |
|||
|
|||
delegate void Mono_ThrowExceptionCallback(IntPtr exception); |
|||
|
|||
[MonoPInvokeCallback(typeof(Mono_ThrowExceptionCallback))] |
|||
static void Mono_throwException(IntPtr exception) { |
|||
throw new Exception(Marshal.PtrToStringAnsi(exception)); |
|||
} |
|||
|
|||
delegate long Mono_TimelineGetMicrosCallback(); |
|||
|
|||
[MonoPInvokeCallback(typeof(Mono_TimelineGetMicrosCallback))] |
|||
static long Mono_timelineGetMicros() { |
|||
return Environment.TickCount * 1000L; |
|||
} |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Mono_hook(Mono_ThrowExceptionCallback throwException, |
|||
Mono_TimelineGetMicrosCallback timelineGetMicros); |
|||
|
|||
|
|||
delegate IntPtr Window_constructorCallback(IntPtr ptr); |
|||
|
|||
[MonoPInvokeCallback(typeof(Window_constructorCallback))] |
|||
static IntPtr Window_constructor(IntPtr ptr) { |
|||
Window window = new Window(); |
|||
window._ptr = ptr; |
|||
return (IntPtr) GCHandle.Alloc(window); |
|||
} |
|||
|
|||
delegate void Window_disposeCallback(IntPtr handle); |
|||
|
|||
[MonoPInvokeCallback(typeof(Window_disposeCallback))] |
|||
static void Window_dispose(IntPtr handle) { |
|||
GCHandle gcHandle = (GCHandle) handle; |
|||
Window window = (Window) gcHandle.Target; |
|||
window._ptr = IntPtr.Zero; |
|||
gcHandle.Free(); |
|||
} |
|||
|
|||
delegate void Window_updateWindowMetricsCallback( |
|||
float devicePixelRatio, |
|||
float width, |
|||
float height, |
|||
float depth, |
|||
float viewPaddingTop, |
|||
float viewPaddingRight, |
|||
float viewPaddingBottom, |
|||
float viewPaddingLeft, |
|||
float viewInsetTop, |
|||
float viewInsetRight, |
|||
float viewInsetBottom, |
|||
float viewInsetLeft, |
|||
float systemGestureInsetTop, |
|||
float systemGestureInsetRight, |
|||
float systemGestureInsetBottom, |
|||
float systemGestureInsetLeft |
|||
); |
|||
|
|||
[MonoPInvokeCallback(typeof(Window_updateWindowMetricsCallback))] |
|||
static void Window_updateWindowMetrics( |
|||
float devicePixelRatio, |
|||
float width, |
|||
float height, |
|||
float depth, |
|||
float viewPaddingTop, |
|||
float viewPaddingRight, |
|||
float viewPaddingBottom, |
|||
float viewPaddingLeft, |
|||
float viewInsetTop, |
|||
float viewInsetRight, |
|||
float viewInsetBottom, |
|||
float viewInsetLeft, |
|||
float systemGestureInsetTop, |
|||
float systemGestureInsetRight, |
|||
float systemGestureInsetBottom, |
|||
float systemGestureInsetLeft |
|||
) { |
|||
var window = Window.instance; |
|||
|
|||
window.devicePixelRatio = devicePixelRatio; |
|||
|
|||
window.physicalSize = new Size(width, height); |
|||
window.physicalDepth = depth; |
|||
|
|||
window.viewPadding = new WindowPadding( |
|||
top: viewPaddingTop, |
|||
right: viewPaddingRight, |
|||
bottom: viewPaddingBottom, |
|||
left: viewPaddingLeft); |
|||
|
|||
window.viewInsets = new WindowPadding( |
|||
top: viewInsetTop, |
|||
right: viewInsetRight, |
|||
bottom: viewInsetBottom, |
|||
left: viewInsetLeft); |
|||
|
|||
window.padding = new WindowPadding( |
|||
top: Mathf.Max(0.0f, viewPaddingTop - viewInsetTop), |
|||
right: Mathf.Max(0.0f, viewPaddingRight - viewInsetRight), |
|||
bottom: Mathf.Max(0.0f, viewPaddingBottom - viewInsetBottom), |
|||
left: Mathf.Max(0.0f, viewPaddingLeft - viewInsetLeft)); |
|||
|
|||
window.systemGestureInsets = new WindowPadding( |
|||
top: Mathf.Max(0.0f, systemGestureInsetTop), |
|||
right: Mathf.Max(0.0f, systemGestureInsetRight), |
|||
bottom: Mathf.Max(0.0f, systemGestureInsetBottom), |
|||
left: Mathf.Max(0.0f, systemGestureInsetLeft)); |
|||
|
|||
window.onMetricsChanged?.Invoke(); |
|||
} |
|||
|
|||
delegate void Window_beginFrameCallback(long microseconds); |
|||
|
|||
[MonoPInvokeCallback(typeof(Window_beginFrameCallback))] |
|||
static void Window_beginFrame(long microseconds) { |
|||
Window.instance.onBeginFrame?.Invoke(TimeSpan.FromMilliseconds(microseconds / 1000.0)); |
|||
} |
|||
|
|||
delegate void Window_drawFrameCallback(); |
|||
|
|||
[MonoPInvokeCallback(typeof(Window_drawFrameCallback))] |
|||
static void Window_drawFrame() { |
|||
Window.instance.onDrawFrame?.Invoke(); |
|||
} |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Window_hook( |
|||
Window_constructorCallback Window_constructor, |
|||
Window_disposeCallback Window_dispose, |
|||
Window_updateWindowMetricsCallback Window_updateWindowMetrics, |
|||
Window_beginFrameCallback Window_beginFrame, |
|||
Window_drawFrameCallback Window_drawFrame); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9757fe323057485caf33e70f71ca8bb0 |
|||
timeCreated: 1597045454 |
|
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.ui2 { |
|||
public static class Isolate { |
|||
|
|||
public static IntPtr current { |
|||
get => Isolate_current(); |
|||
} |
|||
|
|||
public static IDisposable getScope(IntPtr isolate) { |
|||
return new _IsolateDisposable(isolate); |
|||
} |
|||
|
|||
class _IsolateDisposable : IDisposable { |
|||
IntPtr _isolate; |
|||
IntPtr _previous; |
|||
|
|||
public _IsolateDisposable(IntPtr isolate) { |
|||
_isolate = isolate; |
|||
_previous = Isolate_current(); |
|||
if (_previous == _isolate) { |
|||
return; |
|||
} |
|||
|
|||
if (_previous != IntPtr.Zero) { |
|||
Isolate_exit(); |
|||
} |
|||
|
|||
Isolate_enter(_isolate); |
|||
} |
|||
|
|||
public void Dispose() { |
|||
var current = Isolate_current(); |
|||
D.assert(current == IntPtr.Zero || current == _isolate); |
|||
if (_previous == _isolate) { |
|||
return; |
|||
} |
|||
|
|||
if (current != IntPtr.Zero) { |
|||
Isolate_exit(); |
|||
} |
|||
|
|||
if (_previous != IntPtr.Zero) { |
|||
Isolate_enter(_previous); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr Isolate_current(); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Isolate_enter(IntPtr isolate); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Isolate_exit(); |
|||
|
|||
} |
|||
} |
|
|||
using System; |
|||
using Unity.UIWidgets.foundation; |
|||
|
|||
namespace Unity.UIWidgets.ui2 { |
|||
public class NativeBindings { |
|||
#if (UNITY_IOS || UNITY_TVOS || UNITY_WEBGL) && !UNITY_EDITOR
|
|||
internal const string dllName = "__Internal"; |
|||
#else
|
|||
internal const string dllName = "libUIWidgets_d"; |
|||
#endif
|
|||
|
|||
} |
|||
|
|||
public abstract class NativeWrapper { |
|||
protected internal IntPtr _ptr { get; protected set; } |
|||
|
|||
protected NativeWrapper() { |
|||
} |
|||
|
|||
protected NativeWrapper(IntPtr ptr) { |
|||
D.assert(ptr != IntPtr.Zero); |
|||
_ptr = ptr; |
|||
} |
|||
|
|||
~NativeWrapper() { |
|||
if (_ptr != IntPtr.Zero) { |
|||
DisposePtr(_ptr); |
|||
_ptr = IntPtr.Zero; |
|||
} |
|||
} |
|||
|
|||
protected abstract void DisposePtr(IntPtr ptr); |
|||
} |
|||
|
|||
public abstract class NativeWrapperDisposable : IDisposable { |
|||
protected internal IntPtr _ptr { get; protected set; } |
|||
|
|||
protected NativeWrapperDisposable() { |
|||
} |
|||
|
|||
protected NativeWrapperDisposable(IntPtr ptr) { |
|||
D.assert(_ptr != IntPtr.Zero); |
|||
_ptr = ptr; |
|||
} |
|||
|
|||
~NativeWrapperDisposable() { |
|||
if (_ptr != IntPtr.Zero) { |
|||
DisposePtr(_ptr); |
|||
_ptr = IntPtr.Zero; |
|||
} |
|||
} |
|||
|
|||
protected abstract void DisposePtr(IntPtr ptr); |
|||
|
|||
public void Dispose() { |
|||
if (_ptr != IntPtr.Zero) { |
|||
DisposePtr(_ptr); |
|||
_ptr = IntPtr.Zero; |
|||
} |
|||
|
|||
GC.SuppressFinalize(this); |
|||
} |
|||
} |
|||
} |
1001
com.unity.uiwidgets/Runtime/ui2/painting.cs
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Runtime.InteropServices; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.ui; |
|||
|
|||
namespace Unity.UIWidgets.ui2 { |
|||
public delegate void VoidCallback(); |
|||
|
|||
public delegate void FrameCallback(TimeSpan duration); |
|||
|
|||
public delegate void TimingsCallback(List<FrameTiming> timings); |
|||
|
|||
public delegate void PointerDataPacketCallback(PointerDataPacket packet); |
|||
|
|||
public unsafe delegate void PlatformMessageResponseCallback(byte* data, int dataLength); |
|||
|
|||
public unsafe delegate void PlatformMessageCallback( |
|||
[MarshalAs(UnmanagedType.LPStr)] string name, byte* data, int dataLength, |
|||
PlatformMessageResponseCallback callback); |
|||
|
|||
delegate void _SetNeedsReportTimingsFunc(IntPtr ptr, bool value); |
|||
|
|||
public enum FramePhase { |
|||
buildStart, |
|||
buildFinish, |
|||
rasterStart, |
|||
rasterFinish, |
|||
} |
|||
|
|||
public class FrameTiming { |
|||
public FrameTiming(List<long> timestamps) { |
|||
D.assert(timestamps.Count == Enum.GetNames(typeof(FramePhase)).Length); |
|||
_timestamps = timestamps; |
|||
} |
|||
|
|||
public long timestampInMicroseconds(FramePhase phase) => _timestamps[(int) phase]; |
|||
|
|||
TimeSpan _rawDuration(FramePhase phase) => TimeSpan.FromMilliseconds(_timestamps[(int) phase] / 1000.0); |
|||
|
|||
public TimeSpan buildDuration => _rawDuration(FramePhase.buildFinish) - _rawDuration(FramePhase.buildStart); |
|||
|
|||
public TimeSpan rasterDuration => _rawDuration(FramePhase.rasterFinish) - _rawDuration(FramePhase.rasterStart); |
|||
|
|||
public TimeSpan totalSpan => _rawDuration(FramePhase.rasterFinish) - _rawDuration(FramePhase.buildStart); |
|||
|
|||
List<long> _timestamps; // in microseconds
|
|||
|
|||
string _formatMS(TimeSpan duration) => $"{duration.Milliseconds}ms"; |
|||
|
|||
public override string ToString() { |
|||
return |
|||
$"{GetType()}(buildDuration: {_formatMS(buildDuration)}, rasterDuration: {_formatMS(rasterDuration)}, totalSpan: {_formatMS(totalSpan)})"; |
|||
} |
|||
} |
|||
|
|||
public enum AppLifecycleState { |
|||
resumed, |
|||
inactive, |
|||
paused, |
|||
detached, |
|||
} |
|||
|
|||
public class WindowPadding { |
|||
internal WindowPadding(float left, float top, float right, float bottom) { |
|||
this.left = left; |
|||
this.top = top; |
|||
this.right = right; |
|||
this.bottom = bottom; |
|||
} |
|||
|
|||
public readonly float left; |
|||
|
|||
public readonly float top; |
|||
|
|||
public readonly float right; |
|||
|
|||
public readonly float bottom; |
|||
|
|||
public static readonly WindowPadding zero = new WindowPadding(left: 0.0f, top: 0.0f, right: 0.0f, bottom: 0.0f); |
|||
|
|||
public override string ToString() { |
|||
return $"{GetType()}(left: {left}, top: {top}, right: {right}, bottom: {bottom})"; |
|||
} |
|||
} |
|||
|
|||
public class Window { |
|||
internal IntPtr _ptr; |
|||
|
|||
internal Window() { |
|||
_setNeedsReportTimings = Window_setNeedsReportTimings; |
|||
} |
|||
|
|||
public static Window instance { |
|||
get { |
|||
GCHandle gcHandle = (GCHandle) Window_instance(); |
|||
return (Window) gcHandle.Target; |
|||
} |
|||
} |
|||
|
|||
public float devicePixelRatio { get; internal set; } = 1.0f; |
|||
|
|||
public Size physicalSize { get; internal set; } = Size.zero; |
|||
|
|||
public float physicalDepth { get; internal set; } = float.MaxValue; |
|||
|
|||
public WindowPadding viewInsets { get; internal set; } = WindowPadding.zero; |
|||
|
|||
public WindowPadding viewPadding { get; internal set; } = WindowPadding.zero; |
|||
|
|||
public WindowPadding systemGestureInsets { get; internal set; } = WindowPadding.zero; |
|||
|
|||
public WindowPadding padding { get; internal set; } = WindowPadding.zero; |
|||
|
|||
public VoidCallback onMetricsChanged { get; set; } |
|||
|
|||
public string initialLifecycleState { |
|||
get { |
|||
_initialLifecycleStateAccessed = true; |
|||
return _initialLifecycleState; |
|||
} |
|||
} |
|||
|
|||
string _initialLifecycleState; |
|||
bool _initialLifecycleStateAccessed = false; |
|||
public float textScaleFactor { get; internal set; } = 1.0f; |
|||
|
|||
public VoidCallback onTextScaleFactorChanged { get; set; } |
|||
|
|||
public bool alwaysUse24HourFormat { get; internal set; } = false; |
|||
|
|||
public Brightness platformBrightness { get; internal set; } = Brightness.light; |
|||
|
|||
public VoidCallback onPlatformBrightnessChanged { get; set; } |
|||
|
|||
public FrameCallback onBeginFrame { get; set; } |
|||
|
|||
public VoidCallback onDrawFrame { get; set; } |
|||
|
|||
TimingsCallback _onReportTimings; |
|||
_SetNeedsReportTimingsFunc _setNeedsReportTimings; |
|||
|
|||
public TimingsCallback onReportTimings { |
|||
get { return _onReportTimings; } |
|||
set { |
|||
if ((value == null) != (_onReportTimings == null)) { |
|||
_setNeedsReportTimings(_ptr, value != null); |
|||
} |
|||
|
|||
_onReportTimings = value; |
|||
} |
|||
} |
|||
|
|||
public PointerDataPacketCallback onPointerDataPacket { get; set; } |
|||
|
|||
public string defaultRouteName { |
|||
get { |
|||
IntPtr routeNamePtr = Window_defaultRouteName(_ptr); |
|||
string routeName = Marshal.PtrToStringAnsi(routeNamePtr); |
|||
Window_freeDefaultRouteName(routeNamePtr); |
|||
return routeName; |
|||
} |
|||
} |
|||
|
|||
public void scheduleFrame() { |
|||
Window_scheduleFrame(_ptr); |
|||
} |
|||
|
|||
public void render(Scene scene) { |
|||
Window_render(_ptr, scene._ptr); |
|||
} |
|||
|
|||
public AccessibilityFeatures accessibilityFeatures { get; internal set; } = AccessibilityFeatures.zero; |
|||
|
|||
public VoidCallback onAccessibilityFeaturesChanged { get; set; } |
|||
|
|||
public unsafe void sendPlatformMessage(string name, |
|||
byte* data, int dataLength, |
|||
PlatformMessageResponseCallback callback) { |
|||
IntPtr errorPtr = |
|||
Window_sendPlatformMessage(_ptr, name, callback, data, dataLength); |
|||
if (errorPtr != IntPtr.Zero) |
|||
throw new Exception(Marshal.PtrToStringAnsi(errorPtr)); |
|||
} |
|||
|
|||
public PlatformMessageCallback onPlatformMessage { get; set; } |
|||
|
|||
unsafe void _respondToPlatformMessage(int responseId, byte* data, int dataLength) { |
|||
Window_respondToPlatformMessage(_ptr, responseId, data, dataLength); |
|||
} |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr Window_instance(); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Window_setNeedsReportTimings(IntPtr ptr, bool value); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern IntPtr Window_defaultRouteName(IntPtr ptr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Window_freeDefaultRouteName(IntPtr routeNamePtr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Window_scheduleFrame(IntPtr ptr); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern void Window_render(IntPtr ptr, IntPtr scene); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern unsafe IntPtr Window_sendPlatformMessage(IntPtr ptr, string name, |
|||
PlatformMessageResponseCallback callback, |
|||
byte* data, int dataLength); |
|||
|
|||
[DllImport(NativeBindings.dllName)] |
|||
static extern unsafe void Window_respondToPlatformMessage(IntPtr ptr, int responseId, |
|||
byte* data, int dataLength); |
|||
} |
|||
|
|||
public class AccessibilityFeatures : IEquatable<AccessibilityFeatures> { |
|||
internal AccessibilityFeatures(int index) { |
|||
_index = index; |
|||
} |
|||
|
|||
const int _kAccessibleNavigation = 1 << 0; |
|||
const int _kInvertColorsIndex = 1 << 1; |
|||
const int _kDisableAnimationsIndex = 1 << 2; |
|||
const int _kBoldTextIndex = 1 << 3; |
|||
const int _kReduceMotionIndex = 1 << 4; |
|||
const int _kHighContrastIndex = 1 << 5; |
|||
|
|||
readonly int _index; |
|||
|
|||
public static readonly AccessibilityFeatures zero = new AccessibilityFeatures(0); |
|||
|
|||
public bool accessibleNavigation => (_kAccessibleNavigation & _index) != 0; |
|||
|
|||
public bool invertColors => (_kInvertColorsIndex & _index) != 0; |
|||
|
|||
public bool disableAnimations => (_kDisableAnimationsIndex & _index) != 0; |
|||
|
|||
public bool boldText => (_kBoldTextIndex & _index) != 0; |
|||
|
|||
public bool reduceMotion => (_kReduceMotionIndex & _index) != 0; |
|||
|
|||
public bool highContrast => (_kHighContrastIndex & _index) != 0; |
|||
|
|||
public override string ToString() { |
|||
List<String> features = new List<String>(); |
|||
if (accessibleNavigation) |
|||
features.Add("accessibleNavigation"); |
|||
if (invertColors) |
|||
features.Add("invertColors"); |
|||
if (disableAnimations) |
|||
features.Add("disableAnimations"); |
|||
if (boldText) |
|||
features.Add("boldText"); |
|||
if (reduceMotion) |
|||
features.Add("reduceMotion"); |
|||
if (highContrast) |
|||
features.Add("highContrast"); |
|||
return $"AccessibilityFeatures{features}"; |
|||
} |
|||
|
|||
public bool Equals(AccessibilityFeatures other) { |
|||
if (ReferenceEquals(null, other)) { |
|||
return false; |
|||
} |
|||
|
|||
if (ReferenceEquals(this, other)) { |
|||
return true; |
|||
} |
|||
|
|||
return _index == other._index; |
|||
} |
|||
|
|||
public override bool Equals(object obj) { |
|||
if (ReferenceEquals(null, obj)) { |
|||
return false; |
|||
} |
|||
|
|||
if (ReferenceEquals(this, obj)) { |
|||
return true; |
|||
} |
|||
|
|||
if (obj.GetType() != GetType()) { |
|||
return false; |
|||
} |
|||
|
|||
return Equals((AccessibilityFeatures) obj); |
|||
} |
|||
|
|||
public override int GetHashCode() { |
|||
return _index; |
|||
} |
|||
|
|||
public static bool operator ==(AccessibilityFeatures left, AccessibilityFeatures right) { |
|||
return Equals(left, right); |
|||
} |
|||
|
|||
public static bool operator !=(AccessibilityFeatures left, AccessibilityFeatures right) { |
|||
return !Equals(left, right); |
|||
} |
|||
} |
|||
|
|||
public enum Brightness { |
|||
dark, |
|||
light, |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 65763a38b5ea40a2af2abe0a2458105a |
|||
timeCreated: 1597046337 |
|
|||
#include "color_filter.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
fml::RefPtr<ColorFilter> ColorFilter::Create() { |
|||
return fml::MakeRefCounted<ColorFilter>(); |
|||
} |
|||
|
|||
void ColorFilter::initMode(int color, int blend_mode) { |
|||
filter_ = SkColorFilters::Blend(static_cast<SkColor>(color), |
|||
static_cast<SkBlendMode>(blend_mode)); |
|||
} |
|||
|
|||
sk_sp<SkColorFilter> ColorFilter::MakeColorMatrixFilter255( |
|||
const float array[20]) { |
|||
float tmp[20]; |
|||
memcpy(tmp, array, sizeof(tmp)); |
|||
tmp[4] *= 1.0f / 255; |
|||
tmp[9] *= 1.0f / 255; |
|||
tmp[14] *= 1.0f / 255; |
|||
tmp[19] *= 1.0f / 255; |
|||
return SkColorFilters::Matrix(tmp); |
|||
} |
|||
|
|||
void ColorFilter::initMatrix(const float* color_matrix) { |
|||
filter_ = MakeColorMatrixFilter255(color_matrix); |
|||
} |
|||
|
|||
void ColorFilter::initLinearToSrgbGamma() { |
|||
filter_ = SkColorFilters::LinearToSRGBGamma(); |
|||
} |
|||
|
|||
void ColorFilter::initSrgbToLinearGamma() { |
|||
filter_ = SkColorFilters::SRGBToLinearGamma(); |
|||
} |
|||
|
|||
ColorFilter::~ColorFilter() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/memory/ref_counted.h> |
|||
|
|||
#include "include/core/SkColorFilter.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class ColorFilter : public fml::RefCountedThreadSafe<ColorFilter> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(ColorFilter); |
|||
|
|||
public: |
|||
static fml::RefPtr<ColorFilter> Create(); |
|||
|
|||
static sk_sp<SkColorFilter> MakeColorMatrixFilter255(const float array[20]); |
|||
|
|||
void initMode(int color, int blend_mode); |
|||
void initMatrix(const float* color_matrix); |
|||
void initSrgbToLinearGamma(); |
|||
void initLinearToSrgbGamma(); |
|||
|
|||
~ColorFilter(); |
|||
|
|||
sk_sp<SkColorFilter> filter() const { return filter_; } |
|||
|
|||
private: |
|||
sk_sp<SkColorFilter> filter_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "engine_layer.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
EngineLayer::EngineLayer(std::shared_ptr<ContainerLayer> layer) |
|||
: layer_(layer) {} |
|||
|
|||
EngineLayer::~EngineLayer() = default; |
|||
|
|||
size_t EngineLayer::GetAllocationSize() { return 3000; }; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "flow/layers/container_layer.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class EngineLayer : public fml::RefCountedThreadSafe<EngineLayer> { |
|||
public: |
|||
~EngineLayer(); |
|||
|
|||
size_t GetAllocationSize(); |
|||
|
|||
static fml::RefPtr<EngineLayer> MakeRetained( |
|||
std::shared_ptr<ContainerLayer> layer) { |
|||
return fml::MakeRefCounted<EngineLayer>(layer); |
|||
} |
|||
|
|||
std::shared_ptr<ContainerLayer> Layer() const { return layer_; } |
|||
|
|||
private: |
|||
explicit EngineLayer(std::shared_ptr<ContainerLayer> layer); |
|||
std::shared_ptr<ContainerLayer> layer_; |
|||
|
|||
FML_FRIEND_MAKE_REF_COUNTED(EngineLayer); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#define _USE_MATH_DEFINES
|
|||
|
|||
#include "gradient.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
typedef CanvasGradient Gradient; |
|||
|
|||
fml::RefPtr<CanvasGradient> CanvasGradient::Create() { |
|||
return fml::MakeRefCounted<CanvasGradient>(); |
|||
} |
|||
|
|||
void CanvasGradient::initLinear(const float* end_points, int end_points_length, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, |
|||
int color_stops_length, SkTileMode tile_mode, |
|||
const float* matrix4) { |
|||
FML_DCHECK(end_points_length == 4); |
|||
FML_DCHECK(colors_length == color_stops_length || color_stops == nullptr); |
|||
|
|||
static_assert(sizeof(SkPoint) == sizeof(float) * 2, |
|||
"SkPoint doesn't use floats."); |
|||
static_assert(sizeof(SkColor) == sizeof(int32_t), |
|||
"SkColor doesn't use int32_t."); |
|||
|
|||
SkMatrix sk_matrix; |
|||
bool has_matrix = matrix4 != nullptr; |
|||
if (has_matrix) { |
|||
sk_matrix = ToSkMatrix(matrix4); |
|||
} |
|||
|
|||
set_shader(UIMonoState::CreateGPUObject(SkGradientShader::MakeLinear( |
|||
reinterpret_cast<const SkPoint*>(end_points), |
|||
reinterpret_cast<const SkColor*>(colors), color_stops, colors_length, |
|||
tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
|||
} |
|||
|
|||
void CanvasGradient::initRadial(float center_x, float center_y, float radius, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, |
|||
int color_stops_length, SkTileMode tile_mode, |
|||
const float* matrix4) { |
|||
FML_DCHECK(colors_length == color_stops_length || color_stops == nullptr); |
|||
|
|||
static_assert(sizeof(SkColor) == sizeof(int32_t), |
|||
"SkColor doesn't use int32_t."); |
|||
|
|||
SkMatrix sk_matrix; |
|||
bool has_matrix = matrix4 != nullptr; |
|||
if (has_matrix) { |
|||
sk_matrix = ToSkMatrix(matrix4); |
|||
} |
|||
|
|||
set_shader(UIMonoState::CreateGPUObject(SkGradientShader::MakeRadial( |
|||
SkPoint::Make(center_x, center_y), radius, |
|||
reinterpret_cast<const SkColor*>(colors), color_stops, colors_length, |
|||
tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
|||
} |
|||
|
|||
void CanvasGradient::initSweep(float center_x, float center_y, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, int color_stops_length, |
|||
SkTileMode tile_mode, float start_angle, |
|||
float end_angle, const float* matrix4) { |
|||
FML_DCHECK(colors_length == color_stops_length || color_stops == nullptr); |
|||
|
|||
static_assert(sizeof(SkColor) == sizeof(int32_t), |
|||
"SkColor doesn't use int32_t."); |
|||
|
|||
SkMatrix sk_matrix; |
|||
bool has_matrix = matrix4 != nullptr; |
|||
if (has_matrix) { |
|||
sk_matrix = ToSkMatrix(matrix4); |
|||
} |
|||
|
|||
set_shader(UIMonoState::CreateGPUObject(SkGradientShader::MakeSweep( |
|||
center_x, center_y, reinterpret_cast<const SkColor*>(colors), color_stops, |
|||
colors_length, tile_mode, start_angle * 180.0 / M_PI, |
|||
end_angle * 180.0 / M_PI, 0, has_matrix ? &sk_matrix : nullptr))); |
|||
} |
|||
|
|||
void CanvasGradient::initTwoPointConical( |
|||
float start_x, float start_y, float start_radius, float end_x, float end_y, |
|||
float end_radius, const int* colors, int colors_length, |
|||
const float* color_stops, int color_stops_length, SkTileMode tile_mode, |
|||
const float* matrix4) { |
|||
FML_DCHECK(colors_length == color_stops_length || color_stops == nullptr); |
|||
|
|||
static_assert(sizeof(SkColor) == sizeof(int32_t), |
|||
"SkColor doesn't use int32_t."); |
|||
|
|||
SkMatrix sk_matrix; |
|||
bool has_matrix = matrix4 != nullptr; |
|||
if (has_matrix) { |
|||
sk_matrix = ToSkMatrix(matrix4); |
|||
} |
|||
|
|||
set_shader(UIMonoState::CreateGPUObject(SkGradientShader::MakeTwoPointConical( |
|||
SkPoint::Make(start_x, start_y), start_radius, |
|||
SkPoint::Make(end_x, end_y), end_radius, |
|||
reinterpret_cast<const SkColor*>(colors), color_stops, colors_length, |
|||
tile_mode, 0, has_matrix ? &sk_matrix : nullptr))); |
|||
} |
|||
|
|||
CanvasGradient::CanvasGradient() = default; |
|||
|
|||
CanvasGradient::~CanvasGradient() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma |
|||
|
|||
#include "include/effects/SkGradientShader.h" |
|||
#include "lib/ui/painting/matrix.h" |
|||
#include "lib/ui/painting/shader.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// TODO: update this if/when Skia adds Decal mode skbug.com/7638 |
|||
static_assert(kSkTileModeCount >= 3, "Need to update tile mode enum"); |
|||
|
|||
class CanvasGradient : public Shader { |
|||
FML_FRIEND_MAKE_REF_COUNTED(CanvasGradient); |
|||
|
|||
public: |
|||
~CanvasGradient() override; |
|||
|
|||
static fml::RefPtr<CanvasGradient> Create(); |
|||
|
|||
void initLinear(const float* end_points, int end_points_length, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, int color_stops_length, |
|||
SkTileMode tile_mode, const float* matrix4); |
|||
|
|||
void initRadial(float center_x, float center_y, float radius, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, int color_stops_length, |
|||
SkTileMode tile_mode, const float* matrix4); |
|||
|
|||
void initSweep(float center_x, float center_y, const int* colors, |
|||
int colors_length, const float* color_stops, |
|||
int color_stops_length, SkTileMode tile_mode, |
|||
float start_angle, float end_angle, const float* matrix4); |
|||
|
|||
void initTwoPointConical(float start_x, float start_y, float start_radius, |
|||
float end_x, float end_y, float end_radius, |
|||
const int* colors, int colors_length, |
|||
const float* color_stops, int color_stops_length, |
|||
SkTileMode tile_mode, const float* matrix4); |
|||
|
|||
private: |
|||
CanvasGradient(); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "image_filter.h"
|
|||
|
|||
#include "include/effects/SkBlurImageFilter.h"
|
|||
#include "include/effects/SkImageSource.h"
|
|||
#include "include/effects/SkPictureImageFilter.h"
|
|||
#include "matrix.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
fml::RefPtr<ImageFilter> ImageFilter::Create() { |
|||
return fml::MakeRefCounted<ImageFilter>(); |
|||
} |
|||
|
|||
ImageFilter::ImageFilter() = default; |
|||
|
|||
ImageFilter::~ImageFilter() = default; |
|||
|
|||
void ImageFilter::initImage(CanvasImage* image) { |
|||
filter_ = SkImageSource::Make(image->image()); |
|||
} |
|||
|
|||
void ImageFilter::initPicture(Picture* picture) { |
|||
filter_ = SkPictureImageFilter::Make(picture->picture()); |
|||
} |
|||
|
|||
void ImageFilter::initBlur(double sigma_x, double sigma_y) { |
|||
filter_ = SkBlurImageFilter::Make(sigma_x, sigma_y, nullptr, nullptr, |
|||
SkBlurImageFilter::kClamp_TileMode); |
|||
} |
|||
|
|||
void ImageFilter::initMatrix(const float* matrix4, int filterQuality) { |
|||
filter_ = SkImageFilter::MakeMatrixFilter( |
|||
ToSkMatrix(matrix4), static_cast<SkFilterQuality>(filterQuality), |
|||
nullptr); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "image.h" |
|||
#include "include/core/SkImageFilter.h" |
|||
#include "picture.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class ImageFilter : public fml::RefCountedThreadSafe<ImageFilter> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(ImageFilter); |
|||
|
|||
public: |
|||
~ImageFilter(); |
|||
static fml::RefPtr<ImageFilter> Create(); |
|||
|
|||
void initImage(CanvasImage* image); |
|||
void initPicture(Picture*); |
|||
void initBlur(double sigma_x, double sigma_y); |
|||
void initMatrix(const float* matrix4, int filter_quality); |
|||
|
|||
const sk_sp<SkImageFilter>& filter() const { return filter_; } |
|||
|
|||
private: |
|||
ImageFilter(); |
|||
|
|||
sk_sp<SkImageFilter> filter_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "image_shader.h"
|
|||
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
fml::RefPtr<ImageShader> ImageShader::Create() { |
|||
return fml::MakeRefCounted<ImageShader>(); |
|||
} |
|||
|
|||
void ImageShader::initWithImage(CanvasImage* image, SkTileMode tmx, |
|||
SkTileMode tmy, const float* matrix4) { |
|||
if (!image) { |
|||
Mono_ThrowException( |
|||
"ImageShader constructor called with non-genuine Image."); |
|||
} |
|||
SkMatrix sk_matrix = ToSkMatrix(matrix4); |
|||
set_shader(UIMonoState::CreateGPUObject( |
|||
image->image()->makeShader(tmx, tmy, &sk_matrix))); |
|||
} |
|||
|
|||
ImageShader::ImageShader() = default; |
|||
|
|||
ImageShader::~ImageShader() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "gradient.h" |
|||
#include "image.h" |
|||
#include "include/core/SkMatrix.h" |
|||
#include "include/core/SkShader.h" |
|||
#include "matrix.h" |
|||
#include "shader.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class ImageShader : public Shader { |
|||
FML_FRIEND_MAKE_REF_COUNTED(ImageShader); |
|||
|
|||
public: |
|||
~ImageShader() override; |
|||
static fml::RefPtr<ImageShader> Create(); |
|||
|
|||
void initWithImage(CanvasImage* image, SkTileMode tmx, SkTileMode tmy, |
|||
const float* matrix4); |
|||
|
|||
private: |
|||
ImageShader(); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "matrix.h"
|
|||
|
|||
#include "flutter/fml/logging.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// Mappings from SkMatrix-index to input-index.
|
|||
static const int kSkMatrixIndexToMatrix4Index[] = { |
|||
// clang-format off
|
|||
0, 4, 12, |
|||
1, 5, 13, |
|||
3, 7, 15, |
|||
// clang-format on
|
|||
}; |
|||
|
|||
SkMatrix ToSkMatrix(const float* matrix4) { |
|||
FML_DCHECK(matrix4); |
|||
|
|||
SkMatrix sk_matrix; |
|||
for (int i = 0; i < 9; ++i) { |
|||
const int matrix4_index = kSkMatrixIndexToMatrix4Index[i]; |
|||
sk_matrix[i] = matrix4[matrix4_index]; |
|||
} |
|||
return sk_matrix; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "include/core/SkMatrix.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
SkMatrix ToSkMatrix(const float* matrix4); |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "paint.h"
|
|||
|
|||
#include "color_filter.h"
|
|||
#include "flutter/fml/logging.h"
|
|||
#include "image_filter.h"
|
|||
#include "include/core/SkColorFilter.h"
|
|||
#include "include/core/SkImageFilter.h"
|
|||
#include "include/core/SkMaskFilter.h"
|
|||
#include "include/core/SkShader.h"
|
|||
#include "include/core/SkString.h"
|
|||
#include "shader.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
// Indices for 32bit values.
|
|||
constexpr int kIsAntiAliasIndex = 0; |
|||
constexpr int kColorIndex = 1; |
|||
constexpr int kBlendModeIndex = 2; |
|||
constexpr int kStyleIndex = 3; |
|||
constexpr int kStrokeWidthIndex = 4; |
|||
constexpr int kStrokeCapIndex = 5; |
|||
constexpr int kStrokeJoinIndex = 6; |
|||
constexpr int kStrokeMiterLimitIndex = 7; |
|||
constexpr int kFilterQualityIndex = 8; |
|||
constexpr int kMaskFilterIndex = 9; |
|||
constexpr int kMaskFilterBlurStyleIndex = 10; |
|||
constexpr int kMaskFilterSigmaIndex = 11; |
|||
constexpr int kInvertColorIndex = 12; |
|||
constexpr int kDitherIndex = 13; |
|||
constexpr size_t kDataByteCount = 56; // 4 * (last index + 1)
|
|||
|
|||
// Indices for objects.
|
|||
constexpr int kShaderIndex = 0; |
|||
constexpr int kColorFilterIndex = 1; |
|||
constexpr int kImageFilterIndex = 2; |
|||
constexpr int kObjectCount = 3; // One larger than largest object index.
|
|||
|
|||
// Must be kept in sync with the default in painting.cs.
|
|||
constexpr uint32_t kColorDefault = 0xFF000000; |
|||
|
|||
// Must be kept in sync with the default in painting.cs.
|
|||
constexpr uint32_t kBlendModeDefault = |
|||
static_cast<uint32_t>(SkBlendMode::kSrcOver); |
|||
|
|||
// Must be kept in sync with the default in painting.cs, and also with the
|
|||
// default SkPaintDefaults_MiterLimit in Skia (which is not in a public header).
|
|||
constexpr double kStrokeMiterLimitDefault = 4.0; |
|||
|
|||
// A color matrix which inverts colors.
|
|||
// clang-format off
|
|||
constexpr float invert_colors[20] = { |
|||
-1.0, 0, 0, 1.0, 0, |
|||
0, -1.0, 0, 1.0, 0, |
|||
0, 0, -1.0, 1.0, 0, |
|||
1.0, 1.0, 1.0, 1.0, 0 |
|||
}; |
|||
// clang-format on
|
|||
|
|||
// Must be kept in sync with the MaskFilter private constants in painting.cs.
|
|||
enum MaskFilterType { Null, Blur }; |
|||
|
|||
Paint::Paint(void** paint_objects, uint8_t* paint_data) { |
|||
is_null_ = paint_data == nullptr; |
|||
if (is_null_) return; |
|||
|
|||
Mono_Handle values[kObjectCount]; |
|||
if (paint_objects != nullptr) { |
|||
auto shader = static_cast<Shader*>(paint_objects[kShaderIndex]); |
|||
if (shader) { |
|||
paint_.setShader(shader->shader()); |
|||
} |
|||
|
|||
auto color_filter = |
|||
static_cast<ColorFilter*>(paint_objects[kColorFilterIndex]); |
|||
if (color_filter) { |
|||
paint_.setColorFilter(color_filter->filter()); |
|||
} |
|||
|
|||
auto image_filter = |
|||
static_cast<ImageFilter*>(paint_objects[kImageFilterIndex]); |
|||
if (image_filter) { |
|||
paint_.setImageFilter(image_filter->filter()); |
|||
} |
|||
} |
|||
|
|||
const uint32_t* uint_data = reinterpret_cast<const uint32_t*>(paint_data); |
|||
const float* float_data = reinterpret_cast<const float*>(paint_data); |
|||
|
|||
paint_.setAntiAlias(uint_data[kIsAntiAliasIndex] == 0); |
|||
|
|||
uint32_t encoded_color = uint_data[kColorIndex]; |
|||
if (encoded_color) { |
|||
SkColor color = encoded_color ^ kColorDefault; |
|||
paint_.setColor(color); |
|||
} |
|||
|
|||
uint32_t encoded_blend_mode = uint_data[kBlendModeIndex]; |
|||
if (encoded_blend_mode) { |
|||
uint32_t blend_mode = encoded_blend_mode ^ kBlendModeDefault; |
|||
paint_.setBlendMode(static_cast<SkBlendMode>(blend_mode)); |
|||
} |
|||
|
|||
uint32_t style = uint_data[kStyleIndex]; |
|||
if (style) paint_.setStyle(static_cast<SkPaint::Style>(style)); |
|||
|
|||
float stroke_width = float_data[kStrokeWidthIndex]; |
|||
if (stroke_width != 0.0) paint_.setStrokeWidth(stroke_width); |
|||
|
|||
uint32_t stroke_cap = uint_data[kStrokeCapIndex]; |
|||
if (stroke_cap) paint_.setStrokeCap(static_cast<SkPaint::Cap>(stroke_cap)); |
|||
|
|||
uint32_t stroke_join = uint_data[kStrokeJoinIndex]; |
|||
if (stroke_join) |
|||
paint_.setStrokeJoin(static_cast<SkPaint::Join>(stroke_join)); |
|||
|
|||
float stroke_miter_limit = float_data[kStrokeMiterLimitIndex]; |
|||
if (stroke_miter_limit != 0.0) |
|||
paint_.setStrokeMiter(stroke_miter_limit + kStrokeMiterLimitDefault); |
|||
|
|||
uint32_t filter_quality = uint_data[kFilterQualityIndex]; |
|||
if (filter_quality) |
|||
paint_.setFilterQuality(static_cast<SkFilterQuality>(filter_quality)); |
|||
|
|||
if (uint_data[kInvertColorIndex]) { |
|||
sk_sp<SkColorFilter> invert_filter = |
|||
ColorFilter::MakeColorMatrixFilter255(invert_colors); |
|||
sk_sp<SkColorFilter> current_filter = paint_.refColorFilter(); |
|||
if (current_filter) { |
|||
invert_filter = invert_filter->makeComposed(current_filter); |
|||
} |
|||
paint_.setColorFilter(invert_filter); |
|||
} |
|||
|
|||
if (uint_data[kDitherIndex]) { |
|||
paint_.setDither(true); |
|||
} |
|||
|
|||
switch (uint_data[kMaskFilterIndex]) { |
|||
case Null: |
|||
break; |
|||
case Blur: |
|||
SkBlurStyle blur_style = |
|||
static_cast<SkBlurStyle>(uint_data[kMaskFilterBlurStyleIndex]); |
|||
double sigma = float_data[kMaskFilterSigmaIndex]; |
|||
paint_.setMaskFilter(SkMaskFilter::MakeBlur(blur_style, sigma)); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "include/core/SkPaint.h" |
|||
#include "runtime/mono_api.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Paint { |
|||
public: |
|||
Paint() = default; |
|||
Paint(void** paint_objects, uint8_t* paint_data); |
|||
|
|||
const SkPaint* paint() const { return is_null_ ? nullptr : &paint_; } |
|||
|
|||
private: |
|||
SkPaint paint_; |
|||
bool is_null_ = true; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "path.h"
|
|||
|
|||
#define _USE_MATH_DEFINES
|
|||
#include <math.h>
|
|||
|
|||
#include "matrix.h"
|
|||
#include "runtime/mono_state.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
typedef CanvasPath Path; |
|||
|
|||
CanvasPath::CanvasPath() {} |
|||
|
|||
CanvasPath::~CanvasPath() {} |
|||
|
|||
int CanvasPath::getFillType() { return static_cast<int>(path_.getFillType()); } |
|||
|
|||
void CanvasPath::setFillType(int fill_type) { |
|||
path_.setFillType(static_cast<SkPathFillType>(fill_type)); |
|||
} |
|||
|
|||
void CanvasPath::moveTo(float x, float y) { path_.moveTo(x, y); } |
|||
|
|||
void CanvasPath::relativeMoveTo(float x, float y) { path_.rMoveTo(x, y); } |
|||
|
|||
void CanvasPath::lineTo(float x, float y) { path_.lineTo(x, y); } |
|||
|
|||
void CanvasPath::relativeLineTo(float x, float y) { path_.rLineTo(x, y); } |
|||
|
|||
void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) { |
|||
path_.quadTo(x1, y1, x2, y2); |
|||
} |
|||
|
|||
void CanvasPath::relativeQuadraticBezierTo(float x1, float y1, float x2, |
|||
float y2) { |
|||
path_.rQuadTo(x1, y1, x2, y2); |
|||
} |
|||
|
|||
void CanvasPath::cubicTo(float x1, float y1, float x2, float y2, float x3, |
|||
float y3) { |
|||
path_.cubicTo(x1, y1, x2, y2, x3, y3); |
|||
} |
|||
|
|||
void CanvasPath::relativeCubicTo(float x1, float y1, float x2, float y2, |
|||
float x3, float y3) { |
|||
path_.rCubicTo(x1, y1, x2, y2, x3, y3); |
|||
} |
|||
|
|||
void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) { |
|||
path_.conicTo(x1, y1, x2, y2, w); |
|||
} |
|||
|
|||
void CanvasPath::relativeConicTo(float x1, float y1, float x2, float y2, |
|||
float w) { |
|||
path_.rConicTo(x1, y1, x2, y2, w); |
|||
} |
|||
|
|||
void CanvasPath::arcTo(float left, float top, float right, float bottom, |
|||
float startAngle, float sweepAngle, bool forceMoveTo) { |
|||
path_.arcTo(SkRect::MakeLTRB(left, top, right, bottom), |
|||
startAngle * 180.0f / M_PI, sweepAngle * 180.0f / M_PI, |
|||
forceMoveTo); |
|||
} |
|||
|
|||
void CanvasPath::arcToPoint(float arcEndX, float arcEndY, float radiusX, |
|||
float radiusY, float xAxisRotation, bool isLargeArc, |
|||
bool isClockwiseDirection) { |
|||
const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize |
|||
: SkPath::ArcSize::kSmall_ArcSize; |
|||
const auto direction = |
|||
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; |
|||
|
|||
path_.arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX, |
|||
arcEndY); |
|||
} |
|||
|
|||
void CanvasPath::relativeArcToPoint(float arcEndDeltaX, float arcEndDeltaY, |
|||
float radiusX, float radiusY, |
|||
float xAxisRotation, bool isLargeArc, |
|||
bool isClockwiseDirection) { |
|||
const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize |
|||
: SkPath::ArcSize::kSmall_ArcSize; |
|||
const auto direction = |
|||
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; |
|||
path_.rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, |
|||
arcEndDeltaX, arcEndDeltaY); |
|||
} |
|||
|
|||
void CanvasPath::addRect(float left, float top, float right, float bottom) { |
|||
path_.addRect(SkRect::MakeLTRB(left, top, right, bottom)); |
|||
} |
|||
|
|||
void CanvasPath::addOval(float left, float top, float right, float bottom) { |
|||
path_.addOval(SkRect::MakeLTRB(left, top, right, bottom)); |
|||
} |
|||
|
|||
void CanvasPath::addArc(float left, float top, float right, float bottom, |
|||
float startAngle, float sweepAngle) { |
|||
path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), |
|||
startAngle * 180.0f / M_PI, sweepAngle * 180.0 / M_PI); |
|||
} |
|||
|
|||
void CanvasPath::addPolygon(float* points, int points_length, bool close) { |
|||
path_.addPoly(reinterpret_cast<const SkPoint*>(points), points_length / 2, |
|||
close); |
|||
} |
|||
|
|||
void CanvasPath::addRRect(const RRect& rrect) { |
|||
path_.addRRect(rrect.sk_rrect); |
|||
} |
|||
|
|||
void CanvasPath::addPath(CanvasPath* path, float dx, float dy) { |
|||
if (!path) Mono_ThrowException("Path.addPath called with non-genuine Path."); |
|||
path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); |
|||
} |
|||
|
|||
void CanvasPath::addPathWithMatrix(CanvasPath* path, float dx, float dy, |
|||
float* matrix4) { |
|||
if (!path) { |
|||
Mono_ThrowException("Path.addPathWithMatrix called with non-genuine Path."); |
|||
} |
|||
|
|||
SkMatrix matrix = ToSkMatrix(matrix4); |
|||
matrix.setTranslateX(matrix.getTranslateX() + dx); |
|||
matrix.setTranslateY(matrix.getTranslateY() + dy); |
|||
path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); |
|||
} |
|||
|
|||
void CanvasPath::extendWithPath(CanvasPath* path, float dx, float dy) { |
|||
if (!path) |
|||
Mono_ThrowException("Path.extendWithPath called with non-genuine Path."); |
|||
path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); |
|||
} |
|||
|
|||
void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, float dx, float dy, |
|||
float* matrix4) { |
|||
if (!path) { |
|||
Mono_ThrowException("Path.addPathWithMatrix called with non-genuine Path."); |
|||
} |
|||
|
|||
SkMatrix matrix = ToSkMatrix(matrix4); |
|||
matrix.setTranslateX(matrix.getTranslateX() + dx); |
|||
matrix.setTranslateY(matrix.getTranslateY() + dy); |
|||
path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); |
|||
} |
|||
|
|||
void CanvasPath::close() { path_.close(); } |
|||
|
|||
void CanvasPath::reset() { path_.reset(); } |
|||
|
|||
bool CanvasPath::contains(float x, float y) { return path_.contains(x, y); } |
|||
|
|||
fml::RefPtr<CanvasPath> CanvasPath::shift(float dx, float dy) { |
|||
fml::RefPtr<CanvasPath> path = CanvasPath::CreateNew(); |
|||
path_.offset(dx, dy, &path->path_); |
|||
return path; |
|||
} |
|||
|
|||
fml::RefPtr<CanvasPath> CanvasPath::transform(float* matrix4) { |
|||
fml::RefPtr<CanvasPath> path = CanvasPath::CreateNew(); |
|||
path_.transform(ToSkMatrix(matrix4), &path->path_); |
|||
return path; |
|||
} |
|||
|
|||
void CanvasPath::getBounds(float* rect) { |
|||
const SkRect& bounds = path_.getBounds(); |
|||
rect[0] = bounds.left(); |
|||
rect[1] = bounds.top(); |
|||
rect[2] = bounds.right(); |
|||
rect[3] = bounds.bottom(); |
|||
} |
|||
|
|||
bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) { |
|||
return Op(path1->path(), path2->path(), (SkPathOp)operation, &path_); |
|||
} |
|||
|
|||
fml::RefPtr<CanvasPath> CanvasPath::clone() { |
|||
fml::RefPtr<CanvasPath> path = CanvasPath::CreateNew(); |
|||
// per Skia docs, this will create a fast copy
|
|||
// data is shared until the source path or dest path are mutated
|
|||
path->path_ = path_; |
|||
return path; |
|||
} |
|||
|
|||
UIWIDGETS_API(Path*) Path_constructor() { |
|||
const auto path = Path::CreateNew(); |
|||
path->AddRef(); |
|||
return path.get(); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_dispose(Path* ptr) { ptr->Release(); } |
|||
|
|||
UIWIDGETS_API(Path*) Path_clone(Path* ptr) { |
|||
const auto path = ptr->clone(); |
|||
path->AddRef(); |
|||
return path.get(); |
|||
} |
|||
|
|||
UIWIDGETS_API(int) Path_getFillType(Path* ptr) { return ptr->getFillType(); } |
|||
|
|||
UIWIDGETS_API(void) Path_setFillType(Path* ptr, int fillType) { |
|||
ptr->setFillType(fillType); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_moveTo(Path* ptr, float x, float y) { |
|||
ptr->moveTo(x, y); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_relativeMoveTo(Path* ptr, float dx, float dy) { |
|||
ptr->relativeMoveTo(dx, dy); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_lineTo(Path* ptr, float x, float y) { |
|||
ptr->lineTo(x, y); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_relativeLineTo(Path* ptr, float dx, float dy) { |
|||
ptr->relativeLineTo(dx, dy); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_quadraticBezierTo(Path* ptr, float x1, float y1, float x2, float y2) { |
|||
ptr->quadraticBezierTo(x1, y1, x2, y2); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_relativeQuadraticBezierTo(Path* ptr, float x1, float y1, float x2, |
|||
float y2) { |
|||
ptr->relativeQuadraticBezierTo(x1, y1, x2, y2); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_cubicTo(Path* ptr, float x1, float y1, float x2, float y2, float x3, |
|||
float y3) { |
|||
ptr->cubicTo(x1, y1, x2, y2, x3, y3); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_relativeCubicTo(Path* ptr, float x1, float y1, float x2, float y2, |
|||
float x3, float y3) { |
|||
ptr->relativeCubicTo(x1, y1, x2, y2, x3, y3); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_conicTo(Path* ptr, float x1, float y1, float x2, float y2, float w) { |
|||
ptr->conicTo(x1, y1, x2, y2, w); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_relativeConicTo(Path* ptr, float x1, float y1, float x2, float y2, |
|||
float w) { |
|||
ptr->relativeConicTo(x1, y1, x2, y2, w); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_arcTo(Path* ptr, float left, float top, float right, float bottom, |
|||
float startAngle, float sweepAngle, bool forceMoveTo) { |
|||
ptr->arcTo(left, top, right, bottom, startAngle, sweepAngle, forceMoveTo); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_arcToPoint(Path* ptr, float arcEndX, float arcEndY, float radiusX, |
|||
float radiusY, float rotation, bool largeArc, bool clockwise) { |
|||
ptr->arcToPoint(arcEndX, arcEndY, radiusX, radiusY, rotation, largeArc, |
|||
clockwise); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_relativeArcToPoint(Path* ptr, float arcEndX, float arcEndY, float radiusX, |
|||
float radiusY, float rotation, bool largeArc, |
|||
bool clockwise) { |
|||
ptr->relativeArcToPoint(arcEndX, arcEndY, radiusX, radiusY, rotation, |
|||
largeArc, clockwise); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addRect(Path* ptr, float left, float top, float right, float bottom) { |
|||
ptr->addRect(left, top, right, bottom); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addOval(Path* ptr, float left, float top, float right, float bottom) { |
|||
ptr->addOval(left, top, right, bottom); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addArc(Path* ptr, float left, float top, float right, float bottom, |
|||
float startAngle, float sweepAngle) { |
|||
ptr->addArc(left, top, right, bottom, startAngle, sweepAngle); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addPolygon(Path* ptr, float* points, int pointsLength, bool close) { |
|||
ptr->addPolygon(points, pointsLength, close); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addRRect(Path* ptr, float* value32) { ptr->addRRect(RRect(value32)); } |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addPathWithMatrix(Path* ptr, Path* path, float dx, float dy, |
|||
float* matrix4) { |
|||
ptr->addPathWithMatrix(path, dx, dy, matrix4); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_addPath(Path* ptr, Path* path, float dx, float dy) { |
|||
ptr->addPath(path, dx, dy); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_extendWithPathAndMatrix(Path* ptr, Path* path, float dx, float dy, |
|||
float* matrix4) { |
|||
ptr->extendWithPathAndMatrix(path, dx, dy, matrix4); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_extendWithPath(Path* ptr, Path* path, float dx, float dy) { |
|||
ptr->extendWithPath(path, dx, dy); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_close(Path* ptr) { ptr->close(); } |
|||
|
|||
UIWIDGETS_API(void) |
|||
Path_reset(Path* ptr) { ptr->reset(); } |
|||
|
|||
UIWIDGETS_API(bool) |
|||
Path_contains(Path* ptr, float x, float y) { return ptr->contains(x, y); } |
|||
|
|||
UIWIDGETS_API(Path*) Path_shift(Path* ptr, float dx, float dy) { |
|||
const auto new_path = ptr->shift(dx, dy); |
|||
new_path->AddRef(); |
|||
return new_path.get(); |
|||
} |
|||
|
|||
UIWIDGETS_API(Path*) Path_transform(Path* ptr, float* matrix4) { |
|||
const auto new_path = ptr->transform(matrix4); |
|||
new_path->AddRef(); |
|||
return new_path.get(); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Path_getBounds(Path* ptr, float* rect) { |
|||
ptr->getBounds(rect); |
|||
} |
|||
|
|||
UIWIDGETS_API(bool) |
|||
Path_op(Path* ptr, Path* path1, Path* path2, int operation) { |
|||
return ptr->op(path1, path2, operation); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/memory/ref_counted.h> |
|||
|
|||
#include "include/core/SkPath.h" |
|||
#include "include/pathops/SkPathOps.h" |
|||
#include "rrect.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class CanvasPath : public fml::RefCountedThreadSafe<CanvasPath> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(CanvasPath); |
|||
|
|||
public: |
|||
~CanvasPath(); |
|||
|
|||
static fml::RefPtr<CanvasPath> CreateNew() { |
|||
return fml::MakeRefCounted<CanvasPath>(); |
|||
} |
|||
|
|||
int getFillType(); |
|||
void setFillType(int fill_type); |
|||
|
|||
void moveTo(float x, float y); |
|||
void relativeMoveTo(float x, float y); |
|||
void lineTo(float x, float y); |
|||
void relativeLineTo(float x, float y); |
|||
void quadraticBezierTo(float x1, float y1, float x2, float y2); |
|||
void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2); |
|||
void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3); |
|||
void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, |
|||
float y3); |
|||
void conicTo(float x1, float y1, float x2, float y2, float w); |
|||
void relativeConicTo(float x1, float y1, float x2, float y2, float w); |
|||
void arcTo(float left, float top, float right, float bottom, float startAngle, |
|||
float sweepAngle, bool forceMoveTo); |
|||
void arcToPoint(float arcEndX, float arcEndY, float radiusX, float radiusY, |
|||
float xAxisRotation, bool isLargeArc, |
|||
bool isClockwiseDirection); |
|||
void relativeArcToPoint(float arcEndDeltaX, float arcEndDeltaY, float radiusX, |
|||
float radiusY, float xAxisRotation, bool isLargeArc, |
|||
bool isClockwiseDirection); |
|||
void addRect(float left, float top, float right, float bottom); |
|||
void addOval(float left, float top, float right, float bottom); |
|||
void addArc(float left, float top, float right, float bottom, |
|||
float startAngle, float sweepAngle); |
|||
void addPolygon(float* points, int points_length, bool close); |
|||
void addRRect(const RRect& rrect); |
|||
void addPath(CanvasPath* path, float dx, float dy); |
|||
void addPathWithMatrix(CanvasPath* path, float dx, float dy, float* matrix4); |
|||
void extendWithPath(CanvasPath* path, float dx, float dy); |
|||
void extendWithPathAndMatrix(CanvasPath* path, float dx, float dy, |
|||
float* matrix4); |
|||
void close(); |
|||
void reset(); |
|||
bool contains(float x, float y); |
|||
fml::RefPtr<CanvasPath> shift(float dx, float dy); |
|||
fml::RefPtr<CanvasPath> transform(float* matrix4); |
|||
void getBounds(float* bounds); |
|||
bool op(CanvasPath* path1, CanvasPath* path2, int operation); |
|||
fml::RefPtr<CanvasPath> clone(); |
|||
|
|||
const SkPath& path() const { return path_; } |
|||
|
|||
private: |
|||
CanvasPath(); |
|||
|
|||
SkPath path_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "rrect.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
RRect::RRect(float* buffer) { |
|||
is_null = true; |
|||
|
|||
if (buffer == nullptr) return; |
|||
|
|||
SkVector radii[4] = {{buffer[4], buffer[5]}, |
|||
{buffer[6], buffer[7]}, |
|||
{buffer[8], buffer[9]}, |
|||
{buffer[10], buffer[11]}}; |
|||
|
|||
sk_rrect.setRectRadii( |
|||
SkRect::MakeLTRB(buffer[0], buffer[1], buffer[2], buffer[3]), radii); |
|||
|
|||
is_null = false; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "include/core/SkRRect.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class RRect { |
|||
public: |
|||
explicit RRect(float* data); |
|||
|
|||
SkRRect sk_rrect; |
|||
bool is_null; |
|||
}; |
|||
} // namespace uiwidgets |
|
|||
#include "shader.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
Shader::Shader(SkiaGPUObject<SkShader> shader) : shader_(std::move(shader)) {} |
|||
|
|||
Shader::~Shader() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include "flow/skia_gpu_object.h" |
|||
#include "include/core/SkShader.h" |
|||
#include "lib/ui/ui_mono_state.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Shader : public fml::RefCountedThreadSafe<Shader> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(Shader); |
|||
|
|||
public: |
|||
virtual ~Shader(); |
|||
|
|||
sk_sp<SkShader> shader() { return shader_.get(); } |
|||
|
|||
void set_shader(SkiaGPUObject<SkShader> shader) { |
|||
shader_ = std::move(shader); |
|||
} |
|||
|
|||
protected: |
|||
Shader(SkiaGPUObject<SkShader> shader = {}); |
|||
|
|||
private: |
|||
SkiaGPUObject<SkShader> shader_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "vertices.h"
|
|||
|
|||
#include <algorithm>
|
|||
|
|||
#include "runtime/mono_api.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
namespace { |
|||
|
|||
void DecodePoints(float* coords, int coords_length, SkPoint* points) { |
|||
for (int i = 0; i < coords_length; i += 2) |
|||
points[i / 2] = SkPoint::Make(coords[i], coords[i + 1]); |
|||
} |
|||
|
|||
template <typename T> |
|||
void DecodeInts(int32_t* ints, int ints_length, T* out) { |
|||
for (int i = 0; i < ints_length; i++) out[i] = ints[i]; |
|||
} |
|||
|
|||
} // namespace
|
|||
|
|||
Vertices::Vertices() = default; |
|||
|
|||
Vertices::~Vertices() = default; |
|||
|
|||
fml::RefPtr<Vertices> Vertices::Create() { |
|||
return fml::MakeRefCounted<Vertices>(); |
|||
} |
|||
|
|||
bool Vertices::init(SkVertices::VertexMode vertex_mode, float* positions, |
|||
int positions_length, float* texture_coordinates, |
|||
int texture_coordinates_length, int32_t* colors, |
|||
int colors_length, uint16_t* indices, int indices_length) { |
|||
uint32_t builderFlags = 0; |
|||
if (texture_coordinates) |
|||
builderFlags |= SkVertices::kHasTexCoords_BuilderFlag; |
|||
if (colors) builderFlags |= SkVertices::kHasColors_BuilderFlag; |
|||
|
|||
SkVertices::Builder builder(vertex_mode, positions_length / 2, indices_length, |
|||
builderFlags); |
|||
|
|||
if (!builder.isValid()) return false; |
|||
|
|||
// positions are required for SkVertices::Builder
|
|||
FML_DCHECK(positions); |
|||
if (positions) DecodePoints(positions, positions_length, builder.positions()); |
|||
|
|||
if (texture_coordinates) { |
|||
// SkVertices::Builder assumes equal numbers of elements
|
|||
FML_DCHECK(positions_length == texture_coordinates_length); |
|||
DecodePoints(texture_coordinates, texture_coordinates_length, |
|||
builder.texCoords()); |
|||
} |
|||
if (colors) { |
|||
// SkVertices::Builder assumes equal numbers of elements
|
|||
FML_DCHECK(positions_length / 2 == colors_length); |
|||
DecodeInts<SkColor>(colors, colors_length, builder.colors()); |
|||
} |
|||
|
|||
if (indices) { |
|||
std::copy(indices, indices + indices_length, builder.indices()); |
|||
} |
|||
|
|||
vertices_ = builder.detach(); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
UIWIDGETS_API(Vertices*) Vertices_constructor() { |
|||
const auto path = Vertices::Create(); |
|||
path->AddRef(); |
|||
return path.get(); |
|||
} |
|||
|
|||
UIWIDGETS_API(void) Vertices_dispose(Vertices* ptr) { ptr->Release(); } |
|||
|
|||
UIWIDGETS_API(bool) |
|||
Vertices_init(Vertices* ptr, SkVertices::VertexMode vertex_mode, |
|||
float* positions, int positions_length, |
|||
float* texture_coordinates, int texture_coordinates_length, |
|||
int32_t* colors, int colors_length, uint16_t* indices, |
|||
int indices_length) { |
|||
return ptr->init(vertex_mode, positions, positions_length, |
|||
texture_coordinates, texture_coordinates_length, colors, |
|||
colors_length, indices, indices_length); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/memory/ref_counted.h> |
|||
|
|||
#include "include/core/SkVertices.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Vertices : public fml::RefCountedThreadSafe<Vertices> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(Vertices); |
|||
|
|||
public: |
|||
~Vertices(); |
|||
|
|||
static fml::RefPtr<Vertices> Create(); |
|||
|
|||
bool init(SkVertices::VertexMode vertex_mode, float* positions, |
|||
int positions_length, float* texture_coordinates, |
|||
int texture_coordinates_length, int32_t* colors, int colors_length, |
|||
uint16_t* indices, int indices_length); |
|||
|
|||
const sk_sp<SkVertices>& vertices() const { return vertices_; } |
|||
|
|||
private: |
|||
Vertices(); |
|||
|
|||
sk_sp<SkVertices> vertices_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "pointer_data.h"
|
|||
|
|||
#include <string.h>
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
static_assert(sizeof(PointerData) == kBytesPerField * kPointerDataFieldCount, |
|||
"PointerData has the wrong size"); |
|||
|
|||
void PointerData::Clear() { memset(this, 0, sizeof(PointerData)); } |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <stdint.h> |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
static constexpr int kPointerDataFieldCount = 28; |
|||
static constexpr int kBytesPerField = sizeof(int32_t); |
|||
|
|||
enum PointerButtonMouse : int32_t { |
|||
kPointerButtonMousePrimary = 1 << 0, |
|||
kPointerButtonMouseSecondary = 1 << 1, |
|||
kPointerButtonMouseMiddle = 1 << 2, |
|||
kPointerButtonMouseBack = 1 << 3, |
|||
kPointerButtonMouseForward = 1 << 4, |
|||
}; |
|||
|
|||
enum PointerButtonTouch : int32_t { |
|||
kPointerButtonTouchContact = 1 << 0, |
|||
}; |
|||
|
|||
enum PointerButtonStylus : int32_t { |
|||
kPointerButtonStylusContact = 1 << 0, |
|||
kPointerButtonStylusPrimary = 1 << 1, |
|||
kPointerButtonStylusSecondary = 1 << 2, |
|||
}; |
|||
|
|||
struct alignas(8) PointerData { |
|||
enum class Change : int32_t { |
|||
kCancel, |
|||
kAdd, |
|||
kRemove, |
|||
kHover, |
|||
kDown, |
|||
kMove, |
|||
kUp, |
|||
}; |
|||
|
|||
enum class DeviceKind : int32_t { |
|||
kTouch, |
|||
kMouse, |
|||
kStylus, |
|||
kInvertedStylus, |
|||
}; |
|||
|
|||
enum class SignalKind : int32_t { |
|||
kNone, |
|||
kScroll, |
|||
}; |
|||
|
|||
int32_t time_stamp; |
|||
Change change; |
|||
DeviceKind kind; |
|||
SignalKind signal_kind; |
|||
int32_t device; |
|||
int32_t pointer_identifier; |
|||
float physical_x; |
|||
float physical_y; |
|||
float physical_delta_x; |
|||
float physical_delta_y; |
|||
int32_t buttons; |
|||
int32_t obscured; |
|||
int32_t synthesized; |
|||
float pressure; |
|||
float pressure_min; |
|||
float pressure_max; |
|||
float distance; |
|||
float distance_max; |
|||
float size; |
|||
float radius_major; |
|||
float radius_minor; |
|||
float radius_min; |
|||
float radius_max; |
|||
float orientation; |
|||
float tilt; |
|||
int32_t platformData; |
|||
float scroll_delta_x; |
|||
float scroll_delta_y; |
|||
|
|||
void Clear(); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "pointer_data_packet.h"
|
|||
|
|||
#include <string.h>
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
PointerDataPacket::PointerDataPacket(size_t count) |
|||
: data_(count * sizeof(PointerData)) {} |
|||
|
|||
PointerDataPacket::PointerDataPacket(uint8_t* data, size_t num_bytes) |
|||
: data_(data, data + num_bytes) {} |
|||
|
|||
PointerDataPacket::~PointerDataPacket() = default; |
|||
|
|||
void PointerDataPacket::SetPointerData(size_t i, const PointerData& data) { |
|||
memcpy(&data_[i * sizeof(PointerData)], &data, sizeof(PointerData)); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <string.h> |
|||
|
|||
#include <vector> |
|||
|
|||
#include "flutter/fml/macros.h" |
|||
#include "pointer_data.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class PointerDataPacket { |
|||
public: |
|||
explicit PointerDataPacket(size_t count); |
|||
PointerDataPacket(uint8_t* data, size_t num_bytes); |
|||
~PointerDataPacket(); |
|||
|
|||
void SetPointerData(size_t i, const PointerData& data); |
|||
const std::vector<uint8_t>& data() const { return data_; } |
|||
|
|||
private: |
|||
std::vector<uint8_t> data_; |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(PointerDataPacket); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "pointer_data_packet_converter.h"
|
|||
|
|||
#include <string.h>
|
|||
|
|||
#include "flutter/fml/logging.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
PointerDataPacketConverter::PointerDataPacketConverter() : pointer_(0) {} |
|||
|
|||
PointerDataPacketConverter::~PointerDataPacketConverter() = default; |
|||
|
|||
std::unique_ptr<PointerDataPacket> PointerDataPacketConverter::Convert( |
|||
std::unique_ptr<PointerDataPacket> packet) { |
|||
size_t kBytesPerPointerData = kPointerDataFieldCount * kBytesPerField; |
|||
auto buffer = packet->data(); |
|||
size_t buffer_length = buffer.size(); |
|||
|
|||
std::vector<PointerData> converted_pointers; |
|||
// Converts each pointer data in the buffer and stores it in the
|
|||
// converted_pointers.
|
|||
for (size_t i = 0; i < buffer_length / kBytesPerPointerData; i++) { |
|||
PointerData pointer_data; |
|||
memcpy(&pointer_data, &buffer[i * kBytesPerPointerData], |
|||
sizeof(PointerData)); |
|||
ConvertPointerData(pointer_data, converted_pointers); |
|||
} |
|||
|
|||
// Writes converted_pointers into converted_packet.
|
|||
auto converted_packet = |
|||
std::make_unique<PointerDataPacket>(converted_pointers.size()); |
|||
size_t count = 0; |
|||
for (auto& converted_pointer : converted_pointers) { |
|||
converted_packet->SetPointerData(count++, converted_pointer); |
|||
} |
|||
|
|||
return converted_packet; |
|||
} |
|||
|
|||
void PointerDataPacketConverter::ConvertPointerData( |
|||
PointerData pointer_data, std::vector<PointerData>& converted_pointers) { |
|||
if (pointer_data.signal_kind == PointerData::SignalKind::kNone) { |
|||
switch (pointer_data.change) { |
|||
case PointerData::Change::kCancel: { |
|||
// Android's three finger gesture will send a cancel event
|
|||
// to a non-existing pointer. Drops the cancel if pointer
|
|||
// is not previously added.
|
|||
// https://github.com/flutter/flutter/issues/20517
|
|||
auto iter = states_.find(pointer_data.device); |
|||
if (iter != states_.end()) { |
|||
PointerState state = iter->second; |
|||
FML_DCHECK(state.isDown); |
|||
UpdatePointerIdentifier(pointer_data, state, false); |
|||
|
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
// Synthesizes a move event if the location does not match.
|
|||
PointerData synthesized_move_event = pointer_data; |
|||
synthesized_move_event.change = PointerData::Change::kMove; |
|||
synthesized_move_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_move_event, state); |
|||
converted_pointers.push_back(synthesized_move_event); |
|||
} |
|||
|
|||
state.isDown = false; |
|||
states_[pointer_data.device] = state; |
|||
converted_pointers.push_back(pointer_data); |
|||
} |
|||
break; |
|||
} |
|||
case PointerData::Change::kAdd: { |
|||
FML_DCHECK(states_.find(pointer_data.device) == states_.end()); |
|||
EnsurePointerState(pointer_data); |
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
case PointerData::Change::kRemove: { |
|||
// Makes sure we have an existing pointer
|
|||
auto iter = states_.find(pointer_data.device); |
|||
FML_DCHECK(iter != states_.end()); |
|||
PointerState state = iter->second; |
|||
|
|||
if (state.isDown) { |
|||
// Synthesizes cancel event if the pointer is down.
|
|||
PointerData synthesized_cancel_event = pointer_data; |
|||
synthesized_cancel_event.change = PointerData::Change::kCancel; |
|||
synthesized_cancel_event.synthesized = 1; |
|||
UpdatePointerIdentifier(synthesized_cancel_event, state, false); |
|||
|
|||
state.isDown = false; |
|||
states_[synthesized_cancel_event.device] = state; |
|||
converted_pointers.push_back(synthesized_cancel_event); |
|||
} |
|||
|
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
// Synthesizes a hover event if the location does not match.
|
|||
PointerData synthesized_hover_event = pointer_data; |
|||
synthesized_hover_event.change = PointerData::Change::kHover; |
|||
synthesized_hover_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_hover_event, state); |
|||
converted_pointers.push_back(synthesized_hover_event); |
|||
} |
|||
|
|||
states_.erase(pointer_data.device); |
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
case PointerData::Change::kHover: { |
|||
auto iter = states_.find(pointer_data.device); |
|||
PointerState state; |
|||
if (iter == states_.end()) { |
|||
// Synthesizes add event if the pointer is not previously added.
|
|||
PointerData synthesized_add_event = pointer_data; |
|||
synthesized_add_event.change = PointerData::Change::kAdd; |
|||
synthesized_add_event.synthesized = 1; |
|||
state = EnsurePointerState(synthesized_add_event); |
|||
converted_pointers.push_back(synthesized_add_event); |
|||
} else { |
|||
state = iter->second; |
|||
} |
|||
|
|||
FML_DCHECK(!state.isDown); |
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
UpdateDeltaAndState(pointer_data, state); |
|||
converted_pointers.push_back(pointer_data); |
|||
} |
|||
break; |
|||
} |
|||
case PointerData::Change::kDown: { |
|||
auto iter = states_.find(pointer_data.device); |
|||
PointerState state; |
|||
if (iter == states_.end()) { |
|||
// Synthesizes a add event if the pointer is not previously added.
|
|||
PointerData synthesized_add_event = pointer_data; |
|||
synthesized_add_event.change = PointerData::Change::kAdd; |
|||
synthesized_add_event.synthesized = 1; |
|||
state = EnsurePointerState(synthesized_add_event); |
|||
converted_pointers.push_back(synthesized_add_event); |
|||
} else { |
|||
state = iter->second; |
|||
} |
|||
|
|||
FML_DCHECK(!state.isDown); |
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
// Synthesizes a hover event if the location does not match.
|
|||
PointerData synthesized_hover_event = pointer_data; |
|||
synthesized_hover_event.change = PointerData::Change::kHover; |
|||
synthesized_hover_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_hover_event, state); |
|||
converted_pointers.push_back(synthesized_hover_event); |
|||
} |
|||
|
|||
UpdatePointerIdentifier(pointer_data, state, true); |
|||
state.isDown = true; |
|||
states_[pointer_data.device] = state; |
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
case PointerData::Change::kMove: { |
|||
// Makes sure we have an existing pointer in down state
|
|||
auto iter = states_.find(pointer_data.device); |
|||
FML_DCHECK(iter != states_.end()); |
|||
PointerState state = iter->second; |
|||
FML_DCHECK(state.isDown); |
|||
|
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
UpdatePointerIdentifier(pointer_data, state, false); |
|||
UpdateDeltaAndState(pointer_data, state); |
|||
converted_pointers.push_back(pointer_data); |
|||
} |
|||
break; |
|||
} |
|||
case PointerData::Change::kUp: { |
|||
// Makes sure we have an existing pointer in down state
|
|||
auto iter = states_.find(pointer_data.device); |
|||
FML_DCHECK(iter != states_.end()); |
|||
PointerState state = iter->second; |
|||
FML_DCHECK(state.isDown); |
|||
|
|||
UpdatePointerIdentifier(pointer_data, state, false); |
|||
|
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
// Synthesizes a move event if the location does not match.
|
|||
PointerData synthesized_move_event = pointer_data; |
|||
synthesized_move_event.change = PointerData::Change::kMove; |
|||
synthesized_move_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_move_event, state); |
|||
converted_pointers.push_back(synthesized_move_event); |
|||
} |
|||
|
|||
state.isDown = false; |
|||
states_[pointer_data.device] = state; |
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
default: { |
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
} |
|||
} else { |
|||
switch (pointer_data.signal_kind) { |
|||
case PointerData::SignalKind::kScroll: { |
|||
// Makes sure we have an existing pointer
|
|||
auto iter = states_.find(pointer_data.device); |
|||
FML_DCHECK(iter != states_.end()); |
|||
|
|||
PointerState state = iter->second; |
|||
if (LocationNeedsUpdate(pointer_data, state)) { |
|||
if (state.isDown) { |
|||
// Synthesizes a move event if the pointer is down.
|
|||
PointerData synthesized_move_event = pointer_data; |
|||
synthesized_move_event.signal_kind = PointerData::SignalKind::kNone; |
|||
synthesized_move_event.change = PointerData::Change::kMove; |
|||
synthesized_move_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_move_event, state); |
|||
converted_pointers.push_back(synthesized_move_event); |
|||
} else { |
|||
// Synthesizes a hover event if the pointer is up.
|
|||
PointerData synthesized_hover_event = pointer_data; |
|||
synthesized_hover_event.signal_kind = |
|||
PointerData::SignalKind::kNone; |
|||
synthesized_hover_event.change = PointerData::Change::kHover; |
|||
synthesized_hover_event.synthesized = 1; |
|||
|
|||
UpdateDeltaAndState(synthesized_hover_event, state); |
|||
converted_pointers.push_back(synthesized_hover_event); |
|||
} |
|||
} |
|||
|
|||
converted_pointers.push_back(pointer_data); |
|||
break; |
|||
} |
|||
default: { |
|||
// Ignores unknown signal kind.
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
PointerState PointerDataPacketConverter::EnsurePointerState( |
|||
PointerData pointer_data) { |
|||
PointerState state; |
|||
state.pointer_identifier = 0; |
|||
state.isDown = false; |
|||
state.physical_x = pointer_data.physical_x; |
|||
state.physical_y = pointer_data.physical_y; |
|||
states_[pointer_data.device] = state; |
|||
return state; |
|||
} |
|||
|
|||
void PointerDataPacketConverter::UpdateDeltaAndState(PointerData& pointer_data, |
|||
PointerState& state) { |
|||
pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x; |
|||
pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y; |
|||
state.physical_x = pointer_data.physical_x; |
|||
state.physical_y = pointer_data.physical_y; |
|||
states_[pointer_data.device] = state; |
|||
} |
|||
|
|||
bool PointerDataPacketConverter::LocationNeedsUpdate( |
|||
const PointerData& pointer_data, const PointerState& state) { |
|||
return state.physical_x != pointer_data.physical_x || |
|||
state.physical_y != pointer_data.physical_y; |
|||
} |
|||
|
|||
void PointerDataPacketConverter::UpdatePointerIdentifier( |
|||
PointerData& pointer_data, PointerState& state, bool start_new_pointer) { |
|||
if (start_new_pointer) { |
|||
state.pointer_identifier = ++pointer_; |
|||
states_[pointer_data.device] = state; |
|||
} |
|||
pointer_data.pointer_identifier = state.pointer_identifier; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <string.h> |
|||
|
|||
#include <map> |
|||
#include <memory> |
|||
#include <vector> |
|||
|
|||
#include "flutter/fml/macros.h" |
|||
#include "pointer_data_packet.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
struct PointerState { |
|||
int32_t pointer_identifier; |
|||
bool isDown; |
|||
float physical_x; |
|||
float physical_y; |
|||
}; |
|||
|
|||
class PointerDataPacketConverter { |
|||
public: |
|||
PointerDataPacketConverter(); |
|||
~PointerDataPacketConverter(); |
|||
|
|||
std::unique_ptr<PointerDataPacket> Convert( |
|||
std::unique_ptr<PointerDataPacket> packet); |
|||
|
|||
private: |
|||
std::map<int32_t, PointerState> states_; |
|||
|
|||
int32_t pointer_; |
|||
|
|||
void ConvertPointerData(PointerData pointer_data, |
|||
std::vector<PointerData>& converted_pointers); |
|||
|
|||
PointerState EnsurePointerState(PointerData pointer_data); |
|||
|
|||
void UpdateDeltaAndState(PointerData& pointer_data, PointerState& state); |
|||
|
|||
void UpdatePointerIdentifier(PointerData& pointer_data, PointerState& state, |
|||
bool start_new_pointer); |
|||
|
|||
bool LocationNeedsUpdate(const PointerData& pointer_data, |
|||
const PointerState& state); |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(PointerDataPacketConverter); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "viewport_metrics.h"
|
|||
|
|||
#include "flutter/fml/logging.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
ViewportMetrics::ViewportMetrics( |
|||
float p_device_pixel_ratio, float p_physical_width, float p_physical_height, |
|||
float p_physical_padding_top, float p_physical_padding_right, |
|||
float p_physical_padding_bottom, float p_physical_padding_left, |
|||
float p_physical_view_inset_top, float p_physical_view_inset_right, |
|||
float p_physical_view_inset_bottom, float p_physical_view_inset_left, |
|||
float p_physical_system_gesture_inset_top, |
|||
float p_physical_system_gesture_inset_right, |
|||
float p_physical_system_gesture_inset_bottom, |
|||
float p_physical_system_gesture_inset_left) |
|||
: device_pixel_ratio(p_device_pixel_ratio), |
|||
physical_width(p_physical_width), |
|||
physical_height(p_physical_height), |
|||
physical_padding_top(p_physical_padding_top), |
|||
physical_padding_right(p_physical_padding_right), |
|||
physical_padding_bottom(p_physical_padding_bottom), |
|||
physical_padding_left(p_physical_padding_left), |
|||
physical_view_inset_top(p_physical_view_inset_top), |
|||
physical_view_inset_right(p_physical_view_inset_right), |
|||
physical_view_inset_bottom(p_physical_view_inset_bottom), |
|||
physical_view_inset_left(p_physical_view_inset_left), |
|||
physical_system_gesture_inset_top(p_physical_system_gesture_inset_top), |
|||
physical_system_gesture_inset_right( |
|||
p_physical_system_gesture_inset_right), |
|||
physical_system_gesture_inset_bottom( |
|||
p_physical_system_gesture_inset_bottom), |
|||
physical_system_gesture_inset_left(p_physical_system_gesture_inset_left) { |
|||
// Ensure we don't have nonsensical dimensions.
|
|||
FML_DCHECK(physical_width >= 0); |
|||
FML_DCHECK(physical_height >= 0); |
|||
FML_DCHECK(device_pixel_ratio > 0); |
|||
} |
|||
|
|||
ViewportMetrics::ViewportMetrics( |
|||
float p_device_pixel_ratio, float p_physical_width, float p_physical_height, |
|||
float p_physical_depth, float p_physical_padding_top, |
|||
float p_physical_padding_right, float p_physical_padding_bottom, |
|||
float p_physical_padding_left, float p_physical_view_inset_front, |
|||
float p_physical_view_inset_back, float p_physical_view_inset_top, |
|||
float p_physical_view_inset_right, float p_physical_view_inset_bottom, |
|||
float p_physical_view_inset_left) |
|||
: device_pixel_ratio(p_device_pixel_ratio), |
|||
physical_width(p_physical_width), |
|||
physical_height(p_physical_height), |
|||
physical_depth(p_physical_depth), |
|||
physical_padding_top(p_physical_padding_top), |
|||
physical_padding_right(p_physical_padding_right), |
|||
physical_padding_bottom(p_physical_padding_bottom), |
|||
physical_padding_left(p_physical_padding_left), |
|||
physical_view_inset_top(p_physical_view_inset_top), |
|||
physical_view_inset_right(p_physical_view_inset_right), |
|||
physical_view_inset_bottom(p_physical_view_inset_bottom), |
|||
physical_view_inset_left(p_physical_view_inset_left), |
|||
physical_view_inset_front(p_physical_view_inset_front), |
|||
physical_view_inset_back(p_physical_view_inset_back) { |
|||
// Ensure we don't have nonsensical dimensions.
|
|||
FML_DCHECK(physical_width >= 0); |
|||
FML_DCHECK(physical_height >= 0); |
|||
FML_DCHECK(device_pixel_ratio > 0); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
static const float kUnsetDepth = 3.402823E+38f; |
|||
|
|||
struct ViewportMetrics { |
|||
ViewportMetrics() = default; |
|||
ViewportMetrics(const ViewportMetrics& other) = default; |
|||
|
|||
// Create a 2D ViewportMetrics instance. |
|||
ViewportMetrics(float p_device_pixel_ratio, float p_physical_width, |
|||
float p_physical_height, float p_physical_padding_top, |
|||
float p_physical_padding_right, |
|||
float p_physical_padding_bottom, |
|||
float p_physical_padding_left, |
|||
float p_physical_view_inset_top, |
|||
float p_physical_view_inset_right, |
|||
float p_physical_view_inset_bottom, |
|||
float p_physical_view_inset_left, |
|||
float p_physical_system_gesture_inset_top, |
|||
float p_physical_system_gesture_inset_right, |
|||
float p_physical_system_gesture_inset_bottom, |
|||
float p_physical_system_gesture_inset_left); |
|||
|
|||
// Create a ViewportMetrics instance that contains z information. |
|||
ViewportMetrics( |
|||
float p_device_pixel_ratio, float p_physical_width, |
|||
float p_physical_height, float p_physical_depth, |
|||
float p_physical_padding_top, float p_physical_padding_right, |
|||
float p_physical_padding_bottom, float p_physical_padding_left, |
|||
float p_physical_view_inset_front, float p_physical_view_inset_back, |
|||
float p_physical_view_inset_top, float p_physical_view_inset_right, |
|||
float p_physical_view_inset_bottom, float p_physical_view_inset_left); |
|||
|
|||
float device_pixel_ratio = 1.0f; |
|||
float physical_width = 0; |
|||
float physical_height = 0; |
|||
float physical_depth = kUnsetDepth; |
|||
float physical_padding_top = 0; |
|||
float physical_padding_right = 0; |
|||
float physical_padding_bottom = 0; |
|||
float physical_padding_left = 0; |
|||
float physical_view_inset_top = 0; |
|||
float physical_view_inset_right = 0; |
|||
float physical_view_inset_bottom = 0; |
|||
float physical_view_inset_left = 0; |
|||
float physical_view_inset_front = kUnsetDepth; |
|||
float physical_view_inset_back = kUnsetDepth; |
|||
float physical_system_gesture_inset_top = 0; |
|||
float physical_system_gesture_inset_right = 0; |
|||
float physical_system_gesture_inset_bottom = 0; |
|||
float physical_system_gesture_inset_left = 0; |
|||
}; |
|||
|
|||
struct LogicalSize { |
|||
float width = 0.0f; |
|||
float height = 0.0f; |
|||
float depth = kUnsetDepth; |
|||
}; |
|||
|
|||
struct LogicalInset { |
|||
float left = 0.0f; |
|||
float top = 0.0f; |
|||
float right = 0.0f; |
|||
float bottom = 0.0f; |
|||
float front = kUnsetDepth; |
|||
float back = kUnsetDepth; |
|||
}; |
|||
|
|||
struct LogicalMetrics { |
|||
LogicalSize size; |
|||
float scale = 1.0f; |
|||
float scale_z = 1.0f; |
|||
LogicalInset padding; |
|||
LogicalInset view_inset; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "runtime_controller.h"
|
|||
|
|||
#include "flutter/fml/message_loop.h"
|
|||
#include "flutter/fml/trace_event.h"
|
|||
#include "lib/ui/compositing/scene.h"
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
#include "lib/ui/window/window.h"
|
|||
#include "runtime_delegate.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
RuntimeController::RuntimeController( |
|||
RuntimeDelegate& p_client, Settings& p_settings, |
|||
TaskRunners p_task_runners, |
|||
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate, |
|||
fml::WeakPtr<IOManager> p_io_manager, |
|||
fml::RefPtr<SkiaUnrefQueue> p_unref_queue, |
|||
fml::WeakPtr<ImageDecoder> p_image_decoder, |
|||
const std::function<void(int64_t)>& idle_notification_callback, |
|||
const WindowData& p_window_data, |
|||
const fml::closure& p_isolate_create_callback, |
|||
const fml::closure& p_isolate_shutdown_callback) |
|||
: client_(p_client), |
|||
settings_(p_settings), |
|||
task_runners_(p_task_runners), |
|||
snapshot_delegate_(p_snapshot_delegate), |
|||
io_manager_(p_io_manager), |
|||
unref_queue_(p_unref_queue), |
|||
image_decoder_(p_image_decoder), |
|||
idle_notification_callback_(idle_notification_callback), |
|||
window_data_(std::move(p_window_data)), |
|||
isolate_create_callback_(p_isolate_create_callback), |
|||
isolate_shutdown_callback_(p_isolate_shutdown_callback) { |
|||
|
|||
auto strong_root_isolate = |
|||
MonoIsolate::CreateRootIsolate(settings_, //
|
|||
task_runners_, //
|
|||
std::make_unique<Window>(this), //
|
|||
snapshot_delegate_, //
|
|||
io_manager_, //
|
|||
unref_queue_, //
|
|||
image_decoder_ //
|
|||
) |
|||
.lock(); |
|||
|
|||
FML_CHECK(strong_root_isolate) << "Could not create root isolate."; |
|||
|
|||
// The root isolate ivar is weak.
|
|||
root_isolate_ = strong_root_isolate; |
|||
|
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
MonoState::Scope scope(strong_root_isolate); |
|||
window->DidCreateIsolate(); |
|||
if (!FlushRuntimeStateToIsolate()) { |
|||
FML_DLOG(ERROR) << "Could not setup initial isolate state."; |
|||
} |
|||
} else { |
|||
FML_DCHECK(false) << "RuntimeController created without window binding."; |
|||
} |
|||
|
|||
FML_DCHECK(Mono_CurrentIsolate() == nullptr); |
|||
} |
|||
|
|||
RuntimeController::~RuntimeController() { |
|||
FML_DCHECK(Mono_CurrentIsolate() == nullptr); |
|||
std::shared_ptr<MonoIsolate> root_isolate = root_isolate_.lock(); |
|||
if (root_isolate) { |
|||
auto result = root_isolate->Shutdown(); |
|||
if (!result) { |
|||
FML_DLOG(ERROR) << "Could not shutdown the root isolate."; |
|||
} |
|||
root_isolate_ = {}; |
|||
} |
|||
} |
|||
|
|||
bool RuntimeController::IsRootIsolateRunning() const { |
|||
//std::shared_ptr<MonoIsolate> root_isolate = root_isolate_.lock();
|
|||
//if (root_isolate) {
|
|||
// return root_isolate->GetPhase() == DartIsolate::Phase::Running;
|
|||
//}
|
|||
//return false;
|
|||
return true; |
|||
} |
|||
|
|||
std::unique_ptr<RuntimeController> RuntimeController::Clone() const { |
|||
return std::unique_ptr<RuntimeController>(new RuntimeController( |
|||
client_, //
|
|||
settings_, //
|
|||
task_runners_, //
|
|||
snapshot_delegate_, //
|
|||
io_manager_, //
|
|||
unref_queue_, //
|
|||
image_decoder_, //
|
|||
idle_notification_callback_, //
|
|||
window_data_, //
|
|||
isolate_create_callback_, //
|
|||
isolate_shutdown_callback_ //
|
|||
)); |
|||
} |
|||
|
|||
bool RuntimeController::FlushRuntimeStateToIsolate() { |
|||
return SetViewportMetrics(window_data_.viewport_metrics) && |
|||
SetLocales(window_data_.locale_data) && |
|||
SetAccessibilityFeatures(window_data_.accessibility_feature_flags_) && |
|||
SetUserSettingsData(window_data_.user_settings_data) && |
|||
SetLifecycleState(window_data_.lifecycle_state); |
|||
} |
|||
|
|||
bool RuntimeController::SetViewportMetrics(const ViewportMetrics& metrics) { |
|||
window_data_.viewport_metrics = metrics; |
|||
|
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->UpdateWindowMetrics(metrics); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::SetLocales( |
|||
const std::vector<std::string>& locale_data) { |
|||
window_data_.locale_data = locale_data; |
|||
|
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->UpdateLocales(locale_data); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::SetUserSettingsData(const std::string& data) { |
|||
window_data_.user_settings_data = data; |
|||
|
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->UpdateUserSettingsData(window_data_.user_settings_data); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::SetLifecycleState(const std::string& data) { |
|||
window_data_.lifecycle_state = data; |
|||
|
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->UpdateLifecycleState(window_data_.lifecycle_state); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::SetAccessibilityFeatures(int32_t flags) { |
|||
window_data_.accessibility_feature_flags_ = flags; |
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->UpdateAccessibilityFeatures( |
|||
window_data_.accessibility_feature_flags_); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::BeginFrame(fml::TimePoint frame_time) { |
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->BeginFrame(frame_time); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::ReportTimings(std::vector<int64_t> timings) { |
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
window->ReportTimings(std::move(timings)); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::NotifyIdle(int64_t deadline) { |
|||
std::shared_ptr<MonoIsolate> root_isolate = root_isolate_.lock(); |
|||
if (!root_isolate) { |
|||
return false; |
|||
} |
|||
|
|||
MonoState::Scope scope(root_isolate); |
|||
|
|||
Mono_NotifyIdle(deadline); |
|||
|
|||
// Idle notifications being in isolate scope are part of the contract.
|
|||
if (idle_notification_callback_) { |
|||
TRACE_EVENT0("flutter", "EmbedderIdleNotification"); |
|||
idle_notification_callback_(deadline); |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool RuntimeController::DispatchPlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) { |
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage", |
|||
"mode", "basic"); |
|||
window->DispatchPlatformMessage(std::move(message)); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool RuntimeController::DispatchPointerDataPacket( |
|||
const PointerDataPacket& packet) { |
|||
if (auto* window = GetWindowIfAvailable()) { |
|||
TRACE_EVENT1("flutter", "RuntimeController::DispatchPointerDataPacket", |
|||
"mode", "basic"); |
|||
window->DispatchPointerDataPacket(packet); |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
|
|||
Window* RuntimeController::GetWindowIfAvailable() { |
|||
std::shared_ptr<MonoIsolate> root_isolate = root_isolate_.lock(); |
|||
return root_isolate ? root_isolate->window() : nullptr; |
|||
} |
|||
|
|||
// |WindowClient|
|
|||
std::string RuntimeController::DefaultRouteName() { |
|||
return client_.DefaultRouteName(); |
|||
} |
|||
|
|||
// |WindowClient|
|
|||
void RuntimeController::ScheduleFrame() { |
|||
client_.ScheduleFrame(); |
|||
} |
|||
|
|||
// |WindowClient|
|
|||
void RuntimeController::Render(Scene* scene) { |
|||
client_.Render(scene->takeLayerTree()); |
|||
} |
|||
|
|||
// |WindowClient|
|
|||
void RuntimeController::HandlePlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) { |
|||
client_.HandlePlatformMessage(std::move(message)); |
|||
} |
|||
|
|||
// |WindowClient|
|
|||
FontCollection& RuntimeController::GetFontCollection() { |
|||
// return client_.GetFontCollection();
|
|||
//return nullptr;
|
|||
} |
|||
|
|||
// |WindowClient|
|
|||
void RuntimeController::SetNeedsReportTimings(bool value) { |
|||
client_.SetNeedsReportTimings(value); |
|||
} |
|||
|
|||
|
|||
RuntimeController::Locale::Locale(std::string language_code_, |
|||
std::string country_code_, |
|||
std::string script_code_, |
|||
std::string variant_code_) |
|||
: language_code(language_code_), |
|||
country_code(country_code_), |
|||
script_code(script_code_), |
|||
variant_code(variant_code_) {} |
|||
|
|||
RuntimeController::Locale::~Locale() = default; |
|||
|
|||
} // namespace flutter
|
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <vector> |
|||
|
|||
#include "common/task_runners.h" |
|||
#include "flow/layers/layer_tree.h" |
|||
#include "flutter/fml/macros.h" |
|||
#include "lib/ui/io_manager.h" |
|||
//#include "lib/ui/text/font_collection.h" |
|||
|
|||
#include "lib/ui/ui_mono_state.h" |
|||
#include "lib/ui/window/pointer_data_packet.h" |
|||
#include "lib/ui/window/window.h" |
|||
#include "mono_isolate.h" |
|||
#include "rapidjson/document.h" |
|||
#include "rapidjson/stringbuffer.h" |
|||
#include "runtime/window_data.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Scene; |
|||
class RuntimeDelegate; |
|||
class View; |
|||
class Window; |
|||
|
|||
class RuntimeController final : public WindowClient { |
|||
public: |
|||
RuntimeController( |
|||
RuntimeDelegate& client, |
|||
Settings& settings, |
|||
TaskRunners task_runners, |
|||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate, |
|||
fml::WeakPtr<IOManager> io_manager, |
|||
fml::RefPtr<SkiaUnrefQueue> unref_queue, |
|||
fml::WeakPtr<ImageDecoder> image_decoder, |
|||
const std::function<void(int64_t)>& idle_notification_callback, |
|||
const WindowData& window_data, |
|||
const fml::closure& isolate_create_callback, |
|||
const fml::closure& isolate_shutdown_callback); |
|||
|
|||
~RuntimeController() override; |
|||
|
|||
std::unique_ptr<RuntimeController> Clone() const; |
|||
|
|||
bool SetViewportMetrics(const ViewportMetrics& metrics); |
|||
|
|||
bool SetLocales(const std::vector<std::string>& locale_data); |
|||
|
|||
bool SetUserSettingsData(const std::string& data); |
|||
|
|||
bool SetLifecycleState(const std::string& data); |
|||
|
|||
bool SetAccessibilityFeatures(int32_t flags); |
|||
|
|||
bool BeginFrame(fml::TimePoint frame_time); |
|||
|
|||
bool ReportTimings(std::vector<int64_t> timings); |
|||
|
|||
bool NotifyIdle(int64_t deadline); |
|||
|
|||
bool IsRootIsolateRunning() const; |
|||
|
|||
bool DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
|
|||
bool DispatchPointerDataPacket(const PointerDataPacket& packet); |
|||
|
|||
std::weak_ptr<MonoIsolate> GetRootIsolate(); |
|||
|
|||
private: |
|||
struct Locale { |
|||
Locale(std::string language_code_, std::string country_code_, |
|||
std::string script_code_, std::string variant_code_); |
|||
|
|||
~Locale(); |
|||
|
|||
std::string language_code; |
|||
std::string country_code; |
|||
std::string script_code; |
|||
std::string variant_code; |
|||
}; |
|||
|
|||
RuntimeDelegate& client_; |
|||
Settings& settings_; |
|||
TaskRunners task_runners_; |
|||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate_; |
|||
fml::WeakPtr<IOManager> io_manager_; |
|||
fml::RefPtr<SkiaUnrefQueue> unref_queue_; |
|||
fml::WeakPtr<ImageDecoder> image_decoder_; |
|||
std::function<void(int64_t)> idle_notification_callback_; |
|||
WindowData window_data_; |
|||
std::weak_ptr<MonoIsolate> root_isolate_; |
|||
std::pair<bool, uint32_t> root_isolate_return_code_ = {false, 0}; |
|||
const fml::closure isolate_create_callback_; |
|||
const fml::closure isolate_shutdown_callback_; |
|||
std::shared_ptr<const fml::Mapping> persistent_isolate_data_; |
|||
|
|||
Window* GetWindowIfAvailable(); |
|||
|
|||
bool FlushRuntimeStateToIsolate(); |
|||
|
|||
// |WindowClient| |
|||
std::string DefaultRouteName() override; |
|||
|
|||
// |WindowClient| |
|||
void ScheduleFrame() override; |
|||
|
|||
// |WindowClient| |
|||
void Render(Scene* scene) override; |
|||
|
|||
// |WindowClient| |
|||
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override; |
|||
|
|||
// |WindowClient| |
|||
FontCollection& GetFontCollection() override; |
|||
|
|||
// |WindowClient| |
|||
void SetNeedsReportTimings(bool value) override; |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "runtime_delegate.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
RuntimeDelegate::~RuntimeDelegate() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <vector> |
|||
|
|||
#include "flow/layers/layer_tree.h" |
|||
//#include "lib/ui/text/font_collection.h" |
|||
#include "lib/ui/window/platform_message.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class RuntimeDelegate { |
|||
public: |
|||
virtual std::string DefaultRouteName() = 0; |
|||
|
|||
virtual void ScheduleFrame(bool regenerate_layer_tree = true) = 0; |
|||
|
|||
virtual void Render(std::unique_ptr<LayerTree> layer_tree) = 0; |
|||
|
|||
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) = 0; |
|||
|
|||
// virtual FontCollection& GetFontCollection() = 0; |
|||
|
|||
virtual void SetNeedsReportTimings(bool value) = 0; |
|||
|
|||
protected: |
|||
virtual ~RuntimeDelegate(); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "window_data.h"
|
|||
|
|||
namespace uiwidgets { |
|||
WindowData::WindowData() = default; |
|||
|
|||
WindowData::~WindowData() = default; |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#include "lib/ui/window/viewport_metrics.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
struct WindowData { |
|||
WindowData(); |
|||
|
|||
~WindowData(); |
|||
|
|||
ViewportMetrics viewport_metrics; |
|||
std::string language_code; |
|||
std::string country_code; |
|||
std::string script_code; |
|||
std::string variant_code; |
|||
std::vector<std::string> locale_data; |
|||
std::string user_settings_data = "{}"; |
|||
std::string lifecycle_state; |
|||
int32_t accessibility_feature_flags_ = 0; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "engine.h"
|
|||
|
|||
#include <memory>
|
|||
#include <string>
|
|||
#include <utility>
|
|||
#include <vector>
|
|||
|
|||
#include "common/settings.h"
|
|||
#include "flutter/fml/eintr_wrapper.h"
|
|||
#include "flutter/fml/file.h"
|
|||
#include "flutter/fml/make_copyable.h"
|
|||
#include "flutter/fml/paths.h"
|
|||
#include "flutter/fml/trace_event.h"
|
|||
#include "flutter/fml/unique_fd.h"
|
|||
//#include "lib/snapshot/snapshot.h"
|
|||
//#include "lib/ui/text/font_collection.h"
|
|||
#include "shell/common/animator.h"
|
|||
#include "shell/common/platform_view.h"
|
|||
#include "shell/common/shell.h"
|
|||
#include "rapidjson/document.h"
|
|||
#include "include/core/SkCanvas.h"
|
|||
#include "include/core/SkPictureRecorder.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
static constexpr char kAssetChannel[] = "uiwidgets/assets"; |
|||
static constexpr char kLifecycleChannel[] = "uiwidgets/lifecycle"; |
|||
static constexpr char kNavigationChannel[] = "uiwidgets/navigation"; |
|||
static constexpr char kLocalizationChannel[] = "uiwidgets/localization"; |
|||
static constexpr char kSettingsChannel[] = "uiwidgets/settings"; |
|||
static constexpr char kIsolateChannel[] = "uiwidgets/isolate"; |
|||
|
|||
Engine::Engine(Delegate& delegate, |
|||
const PointerDataDispatcherMaker& dispatcher_maker, |
|||
TaskRunners task_runners, |
|||
const WindowData window_data, |
|||
Settings settings, |
|||
std::unique_ptr<Animator> animator, |
|||
fml::WeakPtr<IOManager> io_manager, |
|||
fml::RefPtr<SkiaUnrefQueue> unref_queue, |
|||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate) |
|||
: delegate_(delegate), |
|||
settings_(std::move(settings)), |
|||
animator_(std::move(animator)), |
|||
activity_running_(true), |
|||
have_surface_(false), |
|||
image_decoder_(task_runners, |
|||
vm.GetConcurrentWorkerTaskRunner(), |
|||
io_manager), |
|||
task_runners_(std::move(task_runners)), |
|||
weak_factory_(this) { |
|||
// Runtime controller is initialized here because it takes a reference to this
|
|||
// object as its delegate. The delegate may be called in the constructor and
|
|||
// we want to be fully initilazed by that point.
|
|||
runtime_controller_ = std::make_unique<RuntimeController>( |
|||
*this, // runtime delegate
|
|||
&vm, // VM
|
|||
std::move(isolate_snapshot), // isolate snapshot
|
|||
task_runners_, // task runners
|
|||
std::move(snapshot_delegate), |
|||
std::move(io_manager), // io manager
|
|||
std::move(unref_queue), // Skia unref queue
|
|||
image_decoder_.GetWeakPtr(), // image decoder
|
|||
settings_.advisory_script_uri, // advisory script uri
|
|||
settings_.advisory_script_entrypoint, // advisory script entrypoint
|
|||
settings_.idle_notification_callback, // idle notification callback
|
|||
window_data, // window data
|
|||
settings_.isolate_create_callback, // isolate create callback
|
|||
settings_.isolate_shutdown_callback, // isolate shutdown callback
|
|||
settings_.persistent_isolate_data // persistent isolate data
|
|||
); |
|||
|
|||
pointer_data_dispatcher_ = dispatcher_maker(*this); |
|||
} |
|||
|
|||
Engine::~Engine() = default; |
|||
|
|||
float Engine::GetDisplayRefreshRate() const { |
|||
return animator_->GetDisplayRefreshRate(); |
|||
} |
|||
|
|||
fml::WeakPtr<Engine> Engine::GetWeakPtr() const { |
|||
return weak_factory_.GetWeakPtr(); |
|||
} |
|||
|
|||
bool Engine::UpdateAssetManager( |
|||
std::shared_ptr<AssetManager> new_asset_manager) { |
|||
if (asset_manager_ == new_asset_manager) { |
|||
return false; |
|||
} |
|||
|
|||
asset_manager_ = new_asset_manager; |
|||
|
|||
if (!asset_manager_) { |
|||
return false; |
|||
} |
|||
|
|||
// Using libTXT as the text engine.
|
|||
font_collection_.RegisterFonts(asset_manager_); |
|||
|
|||
if (settings_.use_test_fonts) { |
|||
font_collection_.RegisterTestFonts(); |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
bool Engine::Restart(RunConfiguration configuration) { |
|||
TRACE_EVENT0("flutter", "Engine::Restart"); |
|||
if (!configuration.IsValid()) { |
|||
FML_LOG(ERROR) << "Engine run configuration was invalid."; |
|||
return false; |
|||
} |
|||
delegate_.OnPreEngineRestart(); |
|||
runtime_controller_ = runtime_controller_->Clone(); |
|||
UpdateAssetManager(nullptr); |
|||
return Run(std::move(configuration)) == Engine::RunStatus::Success; |
|||
} |
|||
|
|||
Engine::RunStatus Engine::Run(RunConfiguration configuration) { |
|||
if (!configuration.IsValid()) { |
|||
FML_LOG(ERROR) << "Engine run configuration was invalid."; |
|||
return RunStatus::Failure; |
|||
} |
|||
|
|||
last_entry_point_ = configuration.GetEntrypoint(); |
|||
last_entry_point_library_ = configuration.GetEntrypointLibrary(); |
|||
|
|||
auto isolate_launch_status = |
|||
PrepareAndLaunchIsolate(std::move(configuration)); |
|||
if (isolate_launch_status == Engine::RunStatus::Failure) { |
|||
FML_LOG(ERROR) << "Engine not prepare and launch isolate."; |
|||
return isolate_launch_status; |
|||
} else if (isolate_launch_status == |
|||
Engine::RunStatus::FailureAlreadyRunning) { |
|||
return isolate_launch_status; |
|||
} |
|||
|
|||
std::shared_ptr<DartIsolate> isolate = |
|||
runtime_controller_->GetRootIsolate().lock(); |
|||
|
|||
bool isolate_running = |
|||
isolate && isolate->GetPhase() == DartIsolate::Phase::Running; |
|||
|
|||
if (isolate_running) { |
|||
tonic::DartState::Scope scope(isolate.get()); |
|||
|
|||
if (settings_.root_isolate_create_callback) { |
|||
settings_.root_isolate_create_callback(); |
|||
} |
|||
|
|||
if (settings_.root_isolate_shutdown_callback) { |
|||
isolate->AddIsolateShutdownCallback( |
|||
settings_.root_isolate_shutdown_callback); |
|||
} |
|||
|
|||
std::string service_id = isolate->GetServiceId(); |
|||
fml::RefPtr<PlatformMessage> service_id_message = |
|||
fml::MakeRefCounted<flutter::PlatformMessage>( |
|||
kIsolateChannel, |
|||
std::vector<uint8_t>(service_id.begin(), service_id.end()), |
|||
nullptr); |
|||
HandlePlatformMessage(service_id_message); |
|||
} |
|||
|
|||
return isolate_running ? Engine::RunStatus::Success |
|||
: Engine::RunStatus::Failure; |
|||
} |
|||
|
|||
Engine::RunStatus Engine::PrepareAndLaunchIsolate( |
|||
RunConfiguration configuration) { |
|||
TRACE_EVENT0("flutter", "Engine::PrepareAndLaunchIsolate"); |
|||
|
|||
UpdateAssetManager(configuration.GetAssetManager()); |
|||
|
|||
auto isolate_configuration = configuration.TakeIsolateConfiguration(); |
|||
|
|||
std::shared_ptr<DartIsolate> isolate = |
|||
runtime_controller_->GetRootIsolate().lock(); |
|||
|
|||
if (!isolate) { |
|||
return RunStatus::Failure; |
|||
} |
|||
|
|||
// This can happen on iOS after a plugin shows a native window and returns to
|
|||
// the Flutter ViewController.
|
|||
if (isolate->GetPhase() == DartIsolate::Phase::Running) { |
|||
FML_DLOG(WARNING) << "Isolate was already running!"; |
|||
return RunStatus::FailureAlreadyRunning; |
|||
} |
|||
|
|||
if (!isolate_configuration->PrepareIsolate(*isolate)) { |
|||
FML_LOG(ERROR) << "Could not prepare to run the isolate."; |
|||
return RunStatus::Failure; |
|||
} |
|||
|
|||
if (configuration.GetEntrypointLibrary().empty()) { |
|||
if (!isolate->Run(configuration.GetEntrypoint(), |
|||
settings_.dart_entrypoint_args)) { |
|||
FML_LOG(ERROR) << "Could not run the isolate."; |
|||
return RunStatus::Failure; |
|||
} |
|||
} else { |
|||
if (!isolate->RunFromLibrary(configuration.GetEntrypointLibrary(), |
|||
configuration.GetEntrypoint(), |
|||
settings_.dart_entrypoint_args)) { |
|||
FML_LOG(ERROR) << "Could not run the isolate."; |
|||
return RunStatus::Failure; |
|||
} |
|||
} |
|||
|
|||
return RunStatus::Success; |
|||
} |
|||
|
|||
void Engine::BeginFrame(fml::TimePoint frame_time) { |
|||
TRACE_EVENT0("flutter", "Engine::BeginFrame"); |
|||
runtime_controller_->BeginFrame(frame_time); |
|||
} |
|||
|
|||
void Engine::ReportTimings(std::vector<int64_t> timings) { |
|||
TRACE_EVENT0("flutter", "Engine::ReportTimings"); |
|||
runtime_controller_->ReportTimings(std::move(timings)); |
|||
} |
|||
|
|||
void Engine::NotifyIdle(int64_t deadline) { |
|||
auto trace_event = std::to_string(deadline - Dart_TimelineGetMicros()); |
|||
TRACE_EVENT1("flutter", "Engine::NotifyIdle", "deadline_now_delta", |
|||
trace_event.c_str()); |
|||
runtime_controller_->NotifyIdle(deadline); |
|||
} |
|||
|
|||
std::pair<bool, uint32_t> Engine::GetUIIsolateReturnCode() { |
|||
return runtime_controller_->GetRootIsolateReturnCode(); |
|||
} |
|||
|
|||
Dart_Port Engine::GetUIIsolateMainPort() { |
|||
return runtime_controller_->GetMainPort(); |
|||
} |
|||
|
|||
std::string Engine::GetUIIsolateName() { |
|||
return runtime_controller_->GetIsolateName(); |
|||
} |
|||
|
|||
bool Engine::UIIsolateHasLivePorts() { |
|||
return runtime_controller_->HasLivePorts(); |
|||
} |
|||
|
|||
tonic::DartErrorHandleType Engine::GetUIIsolateLastError() { |
|||
return runtime_controller_->GetLastError(); |
|||
} |
|||
|
|||
void Engine::OnOutputSurfaceCreated() { |
|||
have_surface_ = true; |
|||
StartAnimatorIfPossible(); |
|||
ScheduleFrame(); |
|||
} |
|||
|
|||
void Engine::OnOutputSurfaceDestroyed() { |
|||
have_surface_ = false; |
|||
StopAnimator(); |
|||
} |
|||
|
|||
void Engine::SetViewportMetrics(const ViewportMetrics& metrics) { |
|||
bool dimensions_changed = |
|||
viewport_metrics_.physical_height != metrics.physical_height || |
|||
viewport_metrics_.physical_width != metrics.physical_width || |
|||
viewport_metrics_.physical_depth != metrics.physical_depth; |
|||
viewport_metrics_ = metrics; |
|||
runtime_controller_->SetViewportMetrics(viewport_metrics_); |
|||
if (animator_) { |
|||
if (dimensions_changed) |
|||
animator_->SetDimensionChangePending(); |
|||
if (have_surface_) |
|||
ScheduleFrame(); |
|||
} |
|||
} |
|||
|
|||
void Engine::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) { |
|||
if (message->channel() == kLifecycleChannel) { |
|||
if (HandleLifecyclePlatformMessage(message.get())) |
|||
return; |
|||
} else if (message->channel() == kLocalizationChannel) { |
|||
if (HandleLocalizationPlatformMessage(message.get())) |
|||
return; |
|||
} else if (message->channel() == kSettingsChannel) { |
|||
HandleSettingsPlatformMessage(message.get()); |
|||
return; |
|||
} |
|||
|
|||
if (runtime_controller_->IsRootIsolateRunning() && |
|||
runtime_controller_->DispatchPlatformMessage(std::move(message))) { |
|||
return; |
|||
} |
|||
|
|||
// If there's no runtime_, we may still need to set the initial route.
|
|||
if (message->channel() == kNavigationChannel) { |
|||
HandleNavigationPlatformMessage(std::move(message)); |
|||
return; |
|||
} |
|||
|
|||
FML_DLOG(WARNING) << "Dropping platform message on channel: " |
|||
<< message->channel(); |
|||
} |
|||
|
|||
bool Engine::HandleLifecyclePlatformMessage(PlatformMessage* message) { |
|||
const auto& data = message->data(); |
|||
std::string state(reinterpret_cast<const char*>(data.data()), data.size()); |
|||
if (state == "AppLifecycleState.paused" || |
|||
state == "AppLifecycleState.detached") { |
|||
activity_running_ = false; |
|||
StopAnimator(); |
|||
} else if (state == "AppLifecycleState.resumed" || |
|||
state == "AppLifecycleState.inactive") { |
|||
activity_running_ = true; |
|||
StartAnimatorIfPossible(); |
|||
} |
|||
|
|||
// Always schedule a frame when the app does become active as per API
|
|||
// recommendation
|
|||
// https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1622956-applicationdidbecomeactive?language=objc
|
|||
if (state == "AppLifecycleState.resumed" && have_surface_) { |
|||
ScheduleFrame(); |
|||
} |
|||
runtime_controller_->SetLifecycleState(state); |
|||
// Always forward these messages to the framework by returning false.
|
|||
return false; |
|||
} |
|||
|
|||
bool Engine::HandleNavigationPlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) { |
|||
const auto& data = message->data(); |
|||
|
|||
rapidjson::Document document; |
|||
document.Parse(reinterpret_cast<const char*>(data.data()), data.size()); |
|||
if (document.HasParseError() || !document.IsObject()) |
|||
return false; |
|||
auto root = document.GetObject(); |
|||
auto method = root.FindMember("method"); |
|||
if (method->value != "setInitialRoute") |
|||
return false; |
|||
auto route = root.FindMember("args"); |
|||
initial_route_ = std::move(route->value.GetString()); |
|||
return true; |
|||
} |
|||
|
|||
bool Engine::HandleLocalizationPlatformMessage(PlatformMessage* message) { |
|||
const auto& data = message->data(); |
|||
|
|||
rapidjson::Document document; |
|||
document.Parse(reinterpret_cast<const char*>(data.data()), data.size()); |
|||
if (document.HasParseError() || !document.IsObject()) |
|||
return false; |
|||
auto root = document.GetObject(); |
|||
auto method = root.FindMember("method"); |
|||
if (method == root.MemberEnd() || method->value != "setLocale") |
|||
return false; |
|||
|
|||
auto args = root.FindMember("args"); |
|||
if (args == root.MemberEnd() || !args->value.IsArray()) |
|||
return false; |
|||
|
|||
const size_t strings_per_locale = 4; |
|||
if (args->value.Size() % strings_per_locale != 0) |
|||
return false; |
|||
std::vector<std::string> locale_data; |
|||
for (size_t locale_index = 0; locale_index < args->value.Size(); |
|||
locale_index += strings_per_locale) { |
|||
if (!args->value[locale_index].IsString() || |
|||
!args->value[locale_index + 1].IsString()) |
|||
return false; |
|||
locale_data.push_back(args->value[locale_index].GetString()); |
|||
locale_data.push_back(args->value[locale_index + 1].GetString()); |
|||
locale_data.push_back(args->value[locale_index + 2].GetString()); |
|||
locale_data.push_back(args->value[locale_index + 3].GetString()); |
|||
} |
|||
|
|||
return runtime_controller_->SetLocales(locale_data); |
|||
} |
|||
|
|||
void Engine::HandleSettingsPlatformMessage(PlatformMessage* message) { |
|||
const auto& data = message->data(); |
|||
std::string jsonData(reinterpret_cast<const char*>(data.data()), data.size()); |
|||
if (runtime_controller_->SetUserSettingsData(std::move(jsonData)) && |
|||
have_surface_) { |
|||
ScheduleFrame(); |
|||
} |
|||
} |
|||
|
|||
void Engine::DispatchPointerDataPacket( |
|||
std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) { |
|||
TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket"); |
|||
TRACE_FLOW_STEP("flutter", "PointerEvent", trace_flow_id); |
|||
pointer_data_dispatcher_->DispatchPacket(std::move(packet), trace_flow_id); |
|||
} |
|||
|
|||
|
|||
void Engine::SetAccessibilityFeatures(int32_t flags) { |
|||
runtime_controller_->SetAccessibilityFeatures(flags); |
|||
} |
|||
|
|||
void Engine::StopAnimator() { |
|||
animator_->Stop(); |
|||
} |
|||
|
|||
void Engine::StartAnimatorIfPossible() { |
|||
if (activity_running_ && have_surface_) |
|||
animator_->Start(); |
|||
} |
|||
|
|||
std::string Engine::DefaultRouteName() { |
|||
if (!initial_route_.empty()) { |
|||
return initial_route_; |
|||
} |
|||
return "/"; |
|||
} |
|||
|
|||
void Engine::ScheduleFrame(bool regenerate_layer_tree) { |
|||
animator_->RequestFrame(regenerate_layer_tree); |
|||
} |
|||
|
|||
void Engine::Render(std::unique_ptr<uiwidgets::LayerTree> layer_tree) { |
|||
if (!layer_tree) |
|||
return; |
|||
|
|||
// Ensure frame dimensions are sane.
|
|||
if (layer_tree->frame_size().isEmpty() || |
|||
layer_tree->frame_physical_depth() <= 0.0f || |
|||
layer_tree->frame_device_pixel_ratio() <= 0.0f) |
|||
return; |
|||
|
|||
animator_->Render(std::move(layer_tree)); |
|||
} |
|||
|
|||
void Engine::UpdateSemantics(SemanticsNodeUpdates update, |
|||
CustomAccessibilityActionUpdates actions) { |
|||
delegate_.OnEngineUpdateSemantics(std::move(update), std::move(actions)); |
|||
} |
|||
|
|||
void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) { |
|||
if (message->channel() == kAssetChannel) { |
|||
HandleAssetPlatformMessage(std::move(message)); |
|||
} else { |
|||
delegate_.OnEngineHandlePlatformMessage(std::move(message)); |
|||
} |
|||
} |
|||
|
|||
void Engine::UpdateIsolateDescription(const std::string isolate_name, |
|||
int64_t isolate_port) { |
|||
delegate_.UpdateIsolateDescription(isolate_name, isolate_port); |
|||
} |
|||
|
|||
void Engine::SetNeedsReportTimings(bool needs_reporting) { |
|||
delegate_.SetNeedsReportTimings(needs_reporting); |
|||
} |
|||
|
|||
FontCollection& Engine::GetFontCollection() { |
|||
return font_collection_; |
|||
} |
|||
|
|||
void Engine::DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) { |
|||
animator_->EnqueueTraceFlowId(trace_flow_id); |
|||
if (runtime_controller_) { |
|||
runtime_controller_->DispatchPointerDataPacket(*packet); |
|||
} |
|||
} |
|||
|
|||
void Engine::ScheduleSecondaryVsyncCallback(const fml::closure& callback) { |
|||
animator_->ScheduleSecondaryVsyncCallback(callback); |
|||
} |
|||
|
|||
void Engine::HandleAssetPlatformMessage(fml::RefPtr<PlatformMessage> message) { |
|||
fml::RefPtr<PlatformMessageResponse> response = message->response(); |
|||
if (!response) { |
|||
return; |
|||
} |
|||
const auto& data = message->data(); |
|||
std::string asset_name(reinterpret_cast<const char*>(data.data()), |
|||
data.size()); |
|||
|
|||
if (asset_manager_) { |
|||
std::unique_ptr<fml::Mapping> asset_mapping = |
|||
asset_manager_->GetAsMapping(asset_name); |
|||
if (asset_mapping) { |
|||
response->Complete(std::move(asset_mapping)); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
response->CompleteEmpty(); |
|||
} |
|||
|
|||
const std::string& Engine::GetLastEntrypoint() const { |
|||
return last_entry_point_; |
|||
} |
|||
|
|||
const std::string& Engine::GetLastEntrypointLibrary() const { |
|||
return last_entry_point_library_; |
|||
} |
|||
|
|||
} // namespace flutter
|
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
|
|||
#include "assets/asset_manager.h" |
|||
#include "common/task_runners.h" |
|||
#include "flutter/fml/macros.h" |
|||
#include "flutter/fml/memory/weak_ptr.h" |
|||
#include "lib/ui/painting/image_decoder.h" |
|||
#include "lib/ui/snapshot_delegate.h" |
|||
//#include "lib/ui/text/font_collection.h" |
|||
#include "include/core/SkPicture.h" |
|||
#include "lib/ui/window/platform_message.h" |
|||
#include "lib/ui/window/viewport_metrics.h" |
|||
#include "runtime/runtime_controller.h" |
|||
#include "runtime/runtime_delegate.h" |
|||
#include "shell/common/animator.h" |
|||
#include "shell/common/platform_view.h" |
|||
#include "shell/common/pointer_data_dispatcher.h" |
|||
#include "shell/common/rasterizer.h" |
|||
#include "shell/common/run_configuration.h" |
|||
#include "shell/common/shell_io_manager.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { |
|||
public: |
|||
enum class RunStatus { |
|||
Success, |
|||
FailureAlreadyRunning, |
|||
Failure, |
|||
}; |
|||
|
|||
class Delegate { |
|||
public: |
|||
virtual void OnEngineHandlePlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) = 0; |
|||
virtual void OnPreEngineRestart() = 0; |
|||
virtual void UpdateIsolateDescription(const std::string isolate_name, |
|||
int64_t isolate_port) = 0; |
|||
virtual void SetNeedsReportTimings(bool needs_reporting) = 0; |
|||
}; |
|||
|
|||
Engine(Delegate& delegate, const PointerDataDispatcherMaker& dispatcher_maker, |
|||
TaskRunners task_runners, const WindowData window_data, |
|||
Settings settings, std::unique_ptr<Animator> animator, |
|||
fml::WeakPtr<IOManager> io_manager, |
|||
fml::RefPtr<SkiaUnrefQueue> unref_queue, |
|||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate); |
|||
|
|||
~Engine() override; |
|||
|
|||
float GetDisplayRefreshRate() const; |
|||
|
|||
fml::WeakPtr<Engine> GetWeakPtr() const; |
|||
|
|||
[[nodiscard]] RunStatus Run(RunConfiguration configuration); |
|||
|
|||
[[nodiscard]] bool Restart(RunConfiguration configuration); |
|||
|
|||
bool UpdateAssetManager(std::shared_ptr<AssetManager> asset_manager); |
|||
|
|||
void BeginFrame(fml::TimePoint frame_time); |
|||
|
|||
void NotifyIdle(int64_t deadline); |
|||
|
|||
void ReportTimings(std::vector<int64_t> timings); |
|||
|
|||
void OnOutputSurfaceCreated(); |
|||
|
|||
void OnOutputSurfaceDestroyed(); |
|||
|
|||
void SetViewportMetrics(const ViewportMetrics& metrics); |
|||
|
|||
void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
|
|||
void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id); |
|||
void SetAccessibilityFeatures(int32_t flags); |
|||
|
|||
void ScheduleFrame(bool regenerate_layer_tree = true) override; |
|||
|
|||
// |RuntimeDelegate| |
|||
// FontCollection& GetFontCollection() override; |
|||
|
|||
// |PointerDataDispatcher::Delegate| |
|||
void DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) override; |
|||
|
|||
// |PointerDataDispatcher::Delegate| |
|||
void ScheduleSecondaryVsyncCallback(const fml::closure& callback) override; |
|||
|
|||
private: |
|||
Engine::Delegate& delegate_; |
|||
const Settings settings_; |
|||
std::unique_ptr<Animator> animator_; |
|||
std::unique_ptr<RuntimeController> runtime_controller_; |
|||
|
|||
// The pointer_data_dispatcher_ depends on animator_ and runtime_controller_. |
|||
// So it should be defined after them to ensure that pointer_data_dispatcher_ |
|||
// is destructed first. |
|||
std::unique_ptr<PointerDataDispatcher> pointer_data_dispatcher_; |
|||
|
|||
std::string last_entry_point_; |
|||
std::string last_entry_point_library_; |
|||
std::string initial_route_; |
|||
ViewportMetrics viewport_metrics_; |
|||
// std::shared_ptr<AssetManager> asset_manager_; |
|||
bool activity_running_; |
|||
bool have_surface_; |
|||
FontCollection font_collection_; |
|||
ImageDecoder image_decoder_; |
|||
TaskRunners task_runners_; |
|||
fml::WeakPtrFactory<Engine> weak_factory_; |
|||
|
|||
// |RuntimeDelegate| |
|||
std::string DefaultRouteName() override; |
|||
|
|||
// |RuntimeDelegate| |
|||
void Render(std::unique_ptr<LayerTree> layer_tree) override; |
|||
|
|||
// |RuntimeDelegate| |
|||
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override; |
|||
|
|||
void SetNeedsReportTimings(bool value) override; |
|||
|
|||
void StopAnimator(); |
|||
|
|||
void StartAnimatorIfPossible(); |
|||
|
|||
bool HandleLifecyclePlatformMessage(PlatformMessage* message); |
|||
|
|||
bool HandleNavigationPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
|
|||
bool HandleLocalizationPlatformMessage(PlatformMessage* message); |
|||
|
|||
void HandleSettingsPlatformMessage(PlatformMessage* message); |
|||
|
|||
void HandleAssetPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
|
|||
bool GetAssetAsBuffer(const std::string& name, std::vector<uint8_t>* data); |
|||
|
|||
RunStatus PrepareAndLaunchIsolate(RunConfiguration configuration); |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(Engine); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "platform_view.h"
|
|||
|
|||
#include <utility>
|
|||
|
|||
#include "flutter/fml/make_copyable.h"
|
|||
#include "flutter/fml/synchronization/waitable_event.h"
|
|||
#include "include/gpu/GrContextOptions.h"
|
|||
#include "include/gpu/gl/GrGLInterface.h"
|
|||
#include "shell/common/rasterizer.h"
|
|||
#include "shell/common/vsync_waiter_fallback.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
PlatformView::PlatformView(Delegate& delegate, TaskRunners task_runners) |
|||
: delegate_(delegate), |
|||
task_runners_(std::move(task_runners)), |
|||
size_(SkISize::Make(0, 0)), |
|||
weak_factory_(this) {} |
|||
|
|||
PlatformView::~PlatformView() = default; |
|||
|
|||
std::unique_ptr<VsyncWaiter> PlatformView::CreateVSyncWaiter() { |
|||
FML_DLOG(WARNING) |
|||
<< "This platform does not provide a Vsync waiter implementation. A " |
|||
"simple timer based fallback is being used."; |
|||
return std::make_unique<VsyncWaiterFallback>(task_runners_); |
|||
} |
|||
|
|||
void PlatformView::DispatchPlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) { |
|||
delegate_.OnPlatformViewDispatchPlatformMessage(std::move(message)); |
|||
} |
|||
|
|||
void PlatformView::DispatchPointerDataPacket( |
|||
std::unique_ptr<PointerDataPacket> packet) { |
|||
delegate_.OnPlatformViewDispatchPointerDataPacket( |
|||
pointer_data_packet_converter_.Convert(std::move(packet))); |
|||
} |
|||
|
|||
void PlatformView::SetAccessibilityFeatures(int32_t flags) { |
|||
delegate_.OnPlatformViewSetAccessibilityFeatures(flags); |
|||
} |
|||
|
|||
void PlatformView::SetViewportMetrics(const ViewportMetrics& metrics) { |
|||
delegate_.OnPlatformViewSetViewportMetrics(metrics); |
|||
} |
|||
|
|||
void PlatformView::NotifyCreated() { |
|||
std::unique_ptr<Surface> surface; |
|||
|
|||
// Threading: We want to use the platform view on the non-platform thread.
|
|||
// Using the weak pointer is illegal. But, we are going to introduce a latch
|
|||
// so that the platform view is not collected till the surface is obtained.
|
|||
auto* platform_view = this; |
|||
fml::ManualResetWaitableEvent latch; |
|||
fml::TaskRunner::RunNowOrPostTask( |
|||
task_runners_.GetRasterTaskRunner(), [platform_view, &surface, &latch]() { |
|||
surface = platform_view->CreateRenderingSurface(); |
|||
latch.Signal(); |
|||
}); |
|||
latch.Wait(); |
|||
delegate_.OnPlatformViewCreated(std::move(surface)); |
|||
} |
|||
|
|||
void PlatformView::NotifyDestroyed() { delegate_.OnPlatformViewDestroyed(); } |
|||
|
|||
sk_sp<GrContext> PlatformView::CreateResourceContext() const { |
|||
FML_DLOG(WARNING) << "This platform does not setup the resource " |
|||
"context on the IO thread for async texture uploads."; |
|||
return nullptr; |
|||
} |
|||
|
|||
void PlatformView::ReleaseResourceContext() const {} |
|||
|
|||
PointerDataDispatcherMaker PlatformView::GetDispatcherMaker() { |
|||
return [](DefaultPointerDataDispatcher::Delegate& delegate) { |
|||
return std::make_unique<DefaultPointerDataDispatcher>(delegate); |
|||
}; |
|||
} |
|||
|
|||
fml::WeakPtr<PlatformView> PlatformView::GetWeakPtr() const { |
|||
return weak_factory_.GetWeakPtr(); |
|||
} |
|||
|
|||
void PlatformView::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) { |
|||
if (auto response = message->response()) response->CompleteEmpty(); |
|||
} |
|||
|
|||
void PlatformView::OnPreEngineRestart() const {} |
|||
|
|||
void PlatformView::RegisterTexture(std::shared_ptr<Texture> texture) { |
|||
delegate_.OnPlatformViewRegisterTexture(std::move(texture)); |
|||
} |
|||
|
|||
void PlatformView::UnregisterTexture(int64_t texture_id) { |
|||
delegate_.OnPlatformViewUnregisterTexture(texture_id); |
|||
} |
|||
|
|||
void PlatformView::MarkTextureFrameAvailable(int64_t texture_id) { |
|||
delegate_.OnPlatformViewMarkTextureFrameAvailable(texture_id); |
|||
} |
|||
|
|||
std::unique_ptr<Surface> PlatformView::CreateRenderingSurface() { |
|||
// We have a default implementation because tests create a platform view but
|
|||
// never a rendering surface.
|
|||
FML_DCHECK(false) << "This platform does not provide a rendering surface but " |
|||
"it was notified of surface rendering surface creation."; |
|||
return nullptr; |
|||
} |
|||
|
|||
void PlatformView::SetNextFrameCallback(const fml::closure& closure) { |
|||
if (!closure) { |
|||
return; |
|||
} |
|||
|
|||
delegate_.OnPlatformViewSetNextFrameCallback(closure); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
|
|||
#include "common/task_runners.h" |
|||
#include "flow/texture.h" |
|||
#include "flutter/fml/macros.h" |
|||
#include "flutter/fml/memory/weak_ptr.h" |
|||
#include "include/core/SkSize.h" |
|||
#include "include/gpu/GrContext.h" |
|||
#include "lib/ui/window/platform_message.h" |
|||
#include "lib/ui/window/pointer_data_packet.h" |
|||
#include "lib/ui/window/pointer_data_packet_converter.h" |
|||
#include "lib/ui/window/viewport_metrics.h" |
|||
#include "shell/common/pointer_data_dispatcher.h" |
|||
#include "shell/common/surface.h" |
|||
#include "shell/common/vsync_waiter.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class PlatformView { |
|||
public: |
|||
class Delegate { |
|||
public: |
|||
virtual void OnPlatformViewCreated(std::unique_ptr<Surface> surface) = 0; |
|||
virtual void OnPlatformViewDestroyed() = 0; |
|||
virtual void OnPlatformViewSetNextFrameCallback( |
|||
const fml::closure& closure) = 0; |
|||
virtual void OnPlatformViewSetViewportMetrics( |
|||
const ViewportMetrics& metrics) = 0; |
|||
virtual void OnPlatformViewDispatchPlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) = 0; |
|||
virtual void OnPlatformViewDispatchPointerDataPacket( |
|||
std::unique_ptr<PointerDataPacket> packet) = 0; |
|||
virtual void OnPlatformViewSetAccessibilityFeatures(int32_t flags) = 0; |
|||
virtual void OnPlatformViewRegisterTexture( |
|||
std::shared_ptr<Texture> texture) = 0; |
|||
virtual void OnPlatformViewUnregisterTexture(int64_t texture_id) = 0; |
|||
virtual void OnPlatformViewMarkTextureFrameAvailable( |
|||
int64_t texture_id) = 0; |
|||
}; |
|||
|
|||
explicit PlatformView(Delegate& delegate, TaskRunners task_runners); |
|||
virtual ~PlatformView(); |
|||
virtual std::unique_ptr<VsyncWaiter> CreateVSyncWaiter(); |
|||
void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message); |
|||
virtual void SetAccessibilityFeatures(int32_t flags); |
|||
void SetViewportMetrics(const ViewportMetrics& metrics); |
|||
void NotifyCreated(); |
|||
virtual void NotifyDestroyed(); |
|||
virtual sk_sp<GrContext> CreateResourceContext() const; |
|||
virtual void ReleaseResourceContext() const; |
|||
virtual PointerDataDispatcherMaker GetDispatcherMaker(); |
|||
fml::WeakPtr<PlatformView> GetWeakPtr() const; |
|||
|
|||
virtual void OnPreEngineRestart() const; |
|||
void SetNextFrameCallback(const fml::closure& closure); |
|||
void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet); |
|||
void RegisterTexture(std::shared_ptr<Texture> texture); |
|||
void UnregisterTexture(int64_t texture_id); |
|||
void MarkTextureFrameAvailable(int64_t texture_id); |
|||
|
|||
protected: |
|||
PlatformView::Delegate& delegate_; |
|||
const TaskRunners task_runners_; |
|||
|
|||
PointerDataPacketConverter pointer_data_packet_converter_; |
|||
SkISize size_; |
|||
fml::WeakPtrFactory<PlatformView> weak_factory_; |
|||
|
|||
// Unlike all other methods on the platform view, this is called on the |
|||
// GPU task runner. |
|||
virtual std::unique_ptr<Surface> CreateRenderingSurface(); |
|||
|
|||
private: |
|||
FML_DISALLOW_COPY_AND_ASSIGN(PlatformView); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
#include "pointer_data_dispatcher.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
PointerDataDispatcher::~PointerDataDispatcher() = default; |
|||
DefaultPointerDataDispatcher::~DefaultPointerDataDispatcher() = default; |
|||
|
|||
SmoothPointerDataDispatcher::SmoothPointerDataDispatcher(Delegate& delegate) |
|||
: DefaultPointerDataDispatcher(delegate), weak_factory_(this) {} |
|||
SmoothPointerDataDispatcher::~SmoothPointerDataDispatcher() = default; |
|||
|
|||
void DefaultPointerDataDispatcher::DispatchPacket( |
|||
std::unique_ptr<PointerDataPacket> packet, uint64_t trace_flow_id) { |
|||
delegate_.DoDispatchPacket(std::move(packet), trace_flow_id); |
|||
} |
|||
|
|||
void SmoothPointerDataDispatcher::DispatchPacket( |
|||
std::unique_ptr<PointerDataPacket> packet, uint64_t trace_flow_id) { |
|||
if (is_pointer_data_in_progress_) { |
|||
if (pending_packet_ != nullptr) { |
|||
DispatchPendingPacket(); |
|||
} |
|||
pending_packet_ = std::move(packet); |
|||
pending_trace_flow_id_ = trace_flow_id; |
|||
} else { |
|||
FML_DCHECK(pending_packet_ == nullptr); |
|||
DefaultPointerDataDispatcher::DispatchPacket(std::move(packet), |
|||
trace_flow_id); |
|||
} |
|||
is_pointer_data_in_progress_ = true; |
|||
ScheduleSecondaryVsyncCallback(); |
|||
} |
|||
|
|||
void SmoothPointerDataDispatcher::ScheduleSecondaryVsyncCallback() { |
|||
delegate_.ScheduleSecondaryVsyncCallback( |
|||
[dispatcher = weak_factory_.GetWeakPtr()]() { |
|||
if (dispatcher && dispatcher->is_pointer_data_in_progress_) { |
|||
if (dispatcher->pending_packet_ != nullptr) { |
|||
dispatcher->DispatchPendingPacket(); |
|||
} else { |
|||
dispatcher->is_pointer_data_in_progress_ = false; |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
void SmoothPointerDataDispatcher::DispatchPendingPacket() { |
|||
FML_DCHECK(pending_packet_ != nullptr); |
|||
FML_DCHECK(is_pointer_data_in_progress_); |
|||
DefaultPointerDataDispatcher::DispatchPacket(std::move(pending_packet_), |
|||
pending_trace_flow_id_); |
|||
pending_packet_ = nullptr; |
|||
pending_trace_flow_id_ = -1; |
|||
ScheduleSecondaryVsyncCallback(); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <flutter/fml/closure.h> |
|||
#include <flutter/fml/memory/weak_ptr.h> |
|||
|
|||
#include <memory> |
|||
|
|||
#include "lib/ui/window/pointer_data_packet.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class PointerDataDispatcher { |
|||
public: |
|||
class Delegate { |
|||
public: |
|||
virtual void DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) = 0; |
|||
|
|||
virtual void ScheduleSecondaryVsyncCallback( |
|||
const fml::closure& callback) = 0; |
|||
}; |
|||
|
|||
virtual void DispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) = 0; |
|||
|
|||
virtual ~PointerDataDispatcher(); |
|||
}; |
|||
|
|||
class DefaultPointerDataDispatcher : public PointerDataDispatcher { |
|||
public: |
|||
DefaultPointerDataDispatcher(Delegate& delegate) : delegate_(delegate) {} |
|||
|
|||
void DispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) override; |
|||
|
|||
virtual ~DefaultPointerDataDispatcher(); |
|||
|
|||
protected: |
|||
Delegate& delegate_; |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(DefaultPointerDataDispatcher); |
|||
}; |
|||
|
|||
class SmoothPointerDataDispatcher : public DefaultPointerDataDispatcher { |
|||
public: |
|||
SmoothPointerDataDispatcher(Delegate& delegate); |
|||
|
|||
void DispatchPacket(std::unique_ptr<PointerDataPacket> packet, |
|||
uint64_t trace_flow_id) override; |
|||
|
|||
virtual ~SmoothPointerDataDispatcher(); |
|||
|
|||
private: |
|||
std::unique_ptr<PointerDataPacket> pending_packet_; |
|||
int pending_trace_flow_id_ = -1; |
|||
|
|||
bool is_pointer_data_in_progress_ = false; |
|||
|
|||
fml::WeakPtrFactory<SmoothPointerDataDispatcher> weak_factory_; |
|||
|
|||
void DispatchPendingPacket(); |
|||
|
|||
void ScheduleSecondaryVsyncCallback(); |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(SmoothPointerDataDispatcher); |
|||
}; |
|||
|
|||
using PointerDataDispatcherMaker = |
|||
std::function<std::unique_ptr<PointerDataDispatcher>( |
|||
PointerDataDispatcher::Delegate&)>; |
|||
|
|||
} // namespace uiwidgets |
1001
engine/src/shell/common/shell.cc
文件差异内容过多而无法显示
查看文件
文件差异内容过多而无法显示
查看文件
|
|||
#pragma once |
|||
|
|||
#include <functional> |
|||
#include <string_view> |
|||
#include <unordered_map> |
|||
|
|||
#include "common/settings.h" |
|||
#include "common/task_runners.h" |
|||
#include "flow/texture.h" |
|||
#include "flutter/fml/closure.h" |
|||
#include "flutter/fml/macros.h" |
|||
#include "flutter/fml/memory/ref_ptr.h" |
|||
#include "flutter/fml/memory/thread_checker.h" |
|||
#include "flutter/fml/memory/weak_ptr.h" |
|||
#include "flutter/fml/status.h" |
|||
#include "flutter/fml/synchronization/sync_switch.h" |
|||
#include "flutter/fml/synchronization/waitable_event.h" |
|||
#include "flutter/fml/thread.h" |
|||
#include "lib/ui/window/platform_message.h" |
|||
#include "shell/common/animator.h" |
|||
#include "shell/common/engine.h" |
|||
#include "shell/common/platform_view.h" |
|||
#include "shell/common/rasterizer.h" |
|||
#include "shell/common/shell_io_manager.h" |
|||
#include "shell/common/surface.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Shell final : public PlatformView::Delegate, |
|||
public Animator::Delegate, |
|||
public Engine::Delegate, |
|||
public Rasterizer::Delegate, |
|||
public ServiceProtocol::Handler { |
|||
public: |
|||
template <class T> |
|||
using CreateCallback = std::function<std::unique_ptr<T>(Shell&)>; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Creates a shell instance using the provided settings. The |
|||
/// callbacks to create the various shell subcomponents will be |
|||
/// called on the appropriate threads before this method returns. |
|||
/// If this is the first instance of a shell in the process, this |
|||
/// call also bootstraps the Dart VM. |
|||
/// |
|||
/// @param[in] task_runners The task runners |
|||
/// @param[in] settings The settings |
|||
/// @param[in] on_create_platform_view The callback that must return a |
|||
/// platform view. This will be called on |
|||
/// the platform task runner before this |
|||
/// method returns. |
|||
/// @param[in] on_create_rasterizer That callback that must provide a |
|||
/// valid rasterizer. This will be called |
|||
/// on the render task runner before this |
|||
/// method returns. |
|||
/// |
|||
/// @return A full initialized shell if the settings and callbacks are |
|||
/// valid. The root isolate has been created but not yet launched. |
|||
/// It may be launched by obtaining the engine weak pointer and |
|||
/// posting a task onto the UI task runner with a valid run |
|||
/// configuration to run the isolate. The embedder must always |
|||
/// check the validity of the shell (using the IsSetup call) |
|||
/// immediately after getting a pointer to it. |
|||
/// |
|||
static std::unique_ptr<Shell> Create( |
|||
TaskRunners task_runners, |
|||
Settings settings, |
|||
const CreateCallback<PlatformView>& on_create_platform_view, |
|||
const CreateCallback<Rasterizer>& on_create_rasterizer); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Creates a shell instance using the provided settings. The |
|||
/// callbacks to create the various shell subcomponents will be |
|||
/// called on the appropriate threads before this method returns. |
|||
/// Unlike the simpler variant of this factory method, this method |
|||
/// allows for specification of window data. If this is the first |
|||
/// instance of a shell in the process, this call also bootstraps |
|||
/// the Dart VM. |
|||
/// |
|||
/// @param[in] task_runners The task runners |
|||
/// @param[in] window_data The default data for setting up |
|||
/// ui.Window that attached to this |
|||
/// intance. |
|||
/// @param[in] settings The settings |
|||
/// @param[in] on_create_platform_view The callback that must return a |
|||
/// platform view. This will be called on |
|||
/// the platform task runner before this |
|||
/// method returns. |
|||
/// @param[in] on_create_rasterizer That callback that must provide a |
|||
/// valid rasterizer. This will be called |
|||
/// on the render task runner before this |
|||
/// method returns. |
|||
/// |
|||
/// @return A full initialized shell if the settings and callbacks are |
|||
/// valid. The root isolate has been created but not yet launched. |
|||
/// It may be launched by obtaining the engine weak pointer and |
|||
/// posting a task onto the UI task runner with a valid run |
|||
/// configuration to run the isolate. The embedder must always |
|||
/// check the validity of the shell (using the IsSetup call) |
|||
/// immediately after getting a pointer to it. |
|||
/// |
|||
static std::unique_ptr<Shell> Create( |
|||
TaskRunners task_runners, |
|||
const WindowData window_data, |
|||
Settings settings, |
|||
CreateCallback<PlatformView> on_create_platform_view, |
|||
CreateCallback<Rasterizer> on_create_rasterizer); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Creates a shell instance using the provided settings. The |
|||
/// callbacks to create the various shell subcomponents will be |
|||
/// called on the appropriate threads before this method returns. |
|||
/// Unlike the simpler variant of this factory method, this method |
|||
/// allows for the specification of an isolate snapshot that |
|||
/// cannot be adequately described in the settings. This call also |
|||
/// requires the specification of a running VM instance. |
|||
/// |
|||
/// @param[in] task_runners The task runners |
|||
/// @param[in] window_data The default data for setting up |
|||
/// ui.Window that attached to this |
|||
/// intance. |
|||
/// @param[in] settings The settings |
|||
/// @param[in] isolate_snapshot A custom isolate snapshot. Takes |
|||
/// precedence over any snapshots |
|||
/// specified in the settings. |
|||
/// @param[in] on_create_platform_view The callback that must return a |
|||
/// platform view. This will be called on |
|||
/// the platform task runner before this |
|||
/// method returns. |
|||
/// @param[in] on_create_rasterizer That callback that must provide a |
|||
/// valid rasterizer. This will be called |
|||
/// on the render task runner before this |
|||
/// method returns. |
|||
/// @param[in] vm A running VM instance. |
|||
/// |
|||
/// @return A full initialized shell if the settings and callbacks are |
|||
/// valid. The root isolate has been created but not yet launched. |
|||
/// It may be launched by obtaining the engine weak pointer and |
|||
/// posting a task onto the UI task runner with a valid run |
|||
/// configuration to run the isolate. The embedder must always |
|||
/// check the validity of the shell (using the IsSetup call) |
|||
/// immediately after getting a pointer to it. |
|||
/// |
|||
static std::unique_ptr<Shell> Create( |
|||
TaskRunners task_runners, |
|||
const WindowData window_data, |
|||
Settings settings, |
|||
fml::RefPtr<const DartSnapshot> isolate_snapshot, |
|||
const CreateCallback<PlatformView>& on_create_platform_view, |
|||
const CreateCallback<Rasterizer>& on_create_rasterizer, |
|||
DartVMRef vm); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Destroys the shell. This is a synchronous operation and |
|||
/// synchronous barrier blocks are introduced on the various |
|||
/// threads to ensure shutdown of all shell sub-components before |
|||
/// this method returns. |
|||
/// |
|||
~Shell(); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Starts an isolate for the given RunConfiguration. |
|||
/// |
|||
void RunEngine(RunConfiguration run_configuration); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Starts an isolate for the given RunConfiguration. The |
|||
/// result_callback will be called with the status of the |
|||
/// operation. |
|||
/// |
|||
void RunEngine(RunConfiguration run_configuration, |
|||
const std::function<void(Engine::RunStatus)>& result_callback); |
|||
|
|||
//------------------------------------------------------------------------------ |
|||
/// @return The settings used to launch this shell. |
|||
/// |
|||
const Settings& GetSettings() const; |
|||
|
|||
//------------------------------------------------------------------------------ |
|||
/// @brief If callers wish to interact directly with any shell |
|||
/// subcomponents, they must (on the platform thread) obtain a |
|||
/// task runner that the component is designed to run on and a |
|||
/// weak pointer to that component. They may then post a task to |
|||
/// that task runner, do the validity check on that task runner |
|||
/// before performing any operation on that component. This |
|||
/// accessor allows callers to access the task runners for this |
|||
/// shell. |
|||
/// |
|||
/// @return The task runners current in use by the shell. |
|||
/// |
|||
const TaskRunners& GetTaskRunners() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Rasterizers may only be accessed on the GPU task runner. |
|||
/// |
|||
/// @return A weak pointer to the rasterizer. |
|||
/// |
|||
fml::WeakPtr<Rasterizer> GetRasterizer() const; |
|||
|
|||
//------------------------------------------------------------------------------ |
|||
/// @brief Engines may only be accessed on the UI thread. This method is |
|||
/// deprecated, and implementers should instead use other API |
|||
/// available on the Shell or the PlatformView. |
|||
/// |
|||
/// @return A weak pointer to the engine. |
|||
/// |
|||
fml::WeakPtr<Engine> GetEngine(); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Platform views may only be accessed on the platform task |
|||
/// runner. |
|||
/// |
|||
/// @return A weak pointer to the platform view. |
|||
/// |
|||
fml::WeakPtr<PlatformView> GetPlatformView(); |
|||
|
|||
// Embedders should call this under low memory conditions to free up |
|||
// internal caches used. |
|||
// |
|||
// This method posts a task to the raster threads to signal the Rasterizer to |
|||
// free resources. |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Used by embedders to notify that there is a low memory |
|||
/// warning. The shell will attempt to purge caches. Current, only |
|||
/// the rasterizer cache is purged. |
|||
void NotifyLowMemoryWarning() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Used by embedders to check if all shell subcomponents are |
|||
/// initialized. It is the embedder's responsibility to make this |
|||
/// call before accessing any other shell method. A shell that is |
|||
/// not setup must be discarded and another one created with |
|||
/// updated settings. |
|||
/// |
|||
/// @return Returns if the shell has been setup. Once set up, this does |
|||
/// not change for the life-cycle of the shell. |
|||
/// |
|||
bool IsSetup() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Captures a screenshot and optionally Base64 encodes the data |
|||
/// of the last layer tree rendered by the rasterizer in this |
|||
/// shell. |
|||
/// |
|||
/// @param[in] type The type of screenshot to capture. |
|||
/// @param[in] base64_encode If the screenshot data should be base64 |
|||
/// encoded. |
|||
/// |
|||
/// @return The screenshot result. |
|||
/// |
|||
Rasterizer::Screenshot Screenshot(Rasterizer::ScreenshotType type, |
|||
bool base64_encode); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Pauses the calling thread until the first frame is presented. |
|||
/// |
|||
/// @return 'kOk' when the first frame has been presented before the timeout |
|||
/// successfully, 'kFailedPrecondition' if called from the GPU or UI |
|||
/// thread, 'kDeadlineExceeded' if there is a timeout. |
|||
/// |
|||
fml::Status WaitForFirstFrame(fml::TimeDelta timeout); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Used by embedders to reload the system fonts in |
|||
/// FontCollection. |
|||
/// It also clears the cached font families and send system |
|||
/// channel message to framework to rebuild affected widgets. |
|||
/// |
|||
/// @return Returns if shell reloads system fonts successfully. |
|||
/// |
|||
bool ReloadSystemFonts(); |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Used by embedders to get the last error from the Dart UI |
|||
/// Isolate, if one exists. |
|||
/// |
|||
/// @return Returns the last error code from the UI Isolate. |
|||
/// |
|||
std::optional<DartErrorCode> GetUIIsolateLastError() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Used by embedders to check if the Engine is running and has |
|||
/// any live ports remaining. For example, the Flutter tester uses |
|||
/// this method to check whether it should continue to wait for |
|||
/// a running test or not. |
|||
/// |
|||
/// @return Returns if the shell has an engine and the engine has any live |
|||
/// Dart ports. |
|||
/// |
|||
bool EngineHasLivePorts() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Accessor for the disable GPU SyncSwitch |
|||
std::shared_ptr<fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() const; |
|||
|
|||
//---------------------------------------------------------------------------- |
|||
/// @brief Get a pointer to the Dart VM used by this running shell |
|||
/// instance. |
|||
/// |
|||
/// @return The Dart VM pointer. |
|||
/// |
|||
DartVM* GetDartVM(); |
|||
|
|||
private: |
|||
using ServiceProtocolHandler = |
|||
std::function<bool(const ServiceProtocol::Handler::ServiceProtocolMap&, |
|||
rapidjson::Document&)>; |
|||
|
|||
const TaskRunners task_runners_; |
|||
const Settings settings_; |
|||
DartVMRef vm_; |
|||
std::unique_ptr<PlatformView> platform_view_; // on platform task runner |
|||
std::unique_ptr<Engine> engine_; // on UI task runner |
|||
std::unique_ptr<Rasterizer> rasterizer_; // on GPU task runner |
|||
std::unique_ptr<ShellIOManager> io_manager_; // on IO task runner |
|||
std::shared_ptr<fml::SyncSwitch> is_gpu_disabled_sync_switch_; |
|||
|
|||
fml::WeakPtr<Engine> weak_engine_; // to be shared across threads |
|||
fml::WeakPtr<Rasterizer> weak_rasterizer_; // to be shared across threads |
|||
fml::WeakPtr<PlatformView> |
|||
weak_platform_view_; // to be shared across threads |
|||
|
|||
std::unordered_map<std::string_view, // method |
|||
std::pair<fml::RefPtr<fml::TaskRunner>, |
|||
ServiceProtocolHandler> // task-runner/function |
|||
// pair |
|||
> |
|||
service_protocol_handlers_; |
|||
bool is_setup_ = false; |
|||
uint64_t next_pointer_flow_id_ = 0; |
|||
|
|||
bool first_frame_rasterized_ = false; |
|||
std::atomic<bool> waiting_for_first_frame_ = true; |
|||
std::mutex waiting_for_first_frame_mutex_; |
|||
std::condition_variable waiting_for_first_frame_condition_; |
|||
|
|||
// Written in the UI thread and read from the raster thread. Hence make it |
|||
// atomic. |
|||
std::atomic<bool> needs_report_timings_{false}; |
|||
|
|||
// Whether there's a task scheduled to report the timings to Dart through |
|||
// ui.Window.onReportTimings. |
|||
bool frame_timings_report_scheduled_ = false; |
|||
|
|||
// Vector of FrameTiming::kCount * n timestamps for n frames whose timings |
|||
// have not been reported yet. Vector of ints instead of FrameTiming is stored |
|||
// here for easier conversions to Dart objects. |
|||
std::vector<int64_t> unreported_timings_; |
|||
|
|||
// A cache of `Engine::GetDisplayRefreshRate` (only callable in the UI thread) |
|||
// so we can access it from `Rasterizer` (in the raster thread). |
|||
// |
|||
// The atomic is for extra thread safety as this is written in the UI thread |
|||
// and read from the raster thread. |
|||
std::atomic<float> display_refresh_rate_ = 0.0f; |
|||
|
|||
// How many frames have been timed since last report. |
|||
size_t UnreportedFramesCount() const; |
|||
|
|||
Shell(DartVMRef vm, TaskRunners task_runners, Settings settings); |
|||
|
|||
static std::unique_ptr<Shell> CreateShellOnPlatformThread( |
|||
DartVMRef vm, |
|||
TaskRunners task_runners, |
|||
const WindowData window_data, |
|||
Settings settings, |
|||
fml::RefPtr<const DartSnapshot> isolate_snapshot, |
|||
const Shell::CreateCallback<PlatformView>& on_create_platform_view, |
|||
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer); |
|||
|
|||
bool Setup(std::unique_ptr<PlatformView> platform_view, |
|||
std::unique_ptr<Engine> engine, |
|||
std::unique_ptr<Rasterizer> rasterizer, |
|||
std::unique_ptr<ShellIOManager> io_manager); |
|||
|
|||
void ReportTimings(); |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewCreated(std::unique_ptr<Surface> surface) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewDestroyed() override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewSetViewportMetrics( |
|||
const ViewportMetrics& metrics) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewDispatchPlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewDispatchPointerDataPacket( |
|||
std::unique_ptr<PointerDataPacket> packet) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewDispatchSemanticsAction( |
|||
int32_t id, |
|||
SemanticsAction action, |
|||
std::vector<uint8_t> args) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewSetSemanticsEnabled(bool enabled) override; |
|||
|
|||
// |shell:PlatformView::Delegate| |
|||
void OnPlatformViewSetAccessibilityFeatures(int32_t flags) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewRegisterTexture( |
|||
std::shared_ptr<flutter::Texture> texture) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewUnregisterTexture(int64_t texture_id) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewMarkTextureFrameAvailable(int64_t texture_id) override; |
|||
|
|||
// |PlatformView::Delegate| |
|||
void OnPlatformViewSetNextFrameCallback(const fml::closure& closure) override; |
|||
|
|||
// |Animator::Delegate| |
|||
void OnAnimatorBeginFrame(fml::TimePoint frame_time) override; |
|||
|
|||
// |Animator::Delegate| |
|||
void OnAnimatorNotifyIdle(int64_t deadline) override; |
|||
|
|||
// |Animator::Delegate| |
|||
void OnAnimatorDraw( |
|||
fml::RefPtr<Pipeline<flutter::LayerTree>> pipeline) override; |
|||
|
|||
// |Animator::Delegate| |
|||
void OnAnimatorDrawLastLayerTree() override; |
|||
|
|||
// |Engine::Delegate| |
|||
void OnEngineUpdateSemantics( |
|||
SemanticsNodeUpdates update, |
|||
CustomAccessibilityActionUpdates actions) override; |
|||
|
|||
// |Engine::Delegate| |
|||
void OnEngineHandlePlatformMessage( |
|||
fml::RefPtr<PlatformMessage> message) override; |
|||
|
|||
void HandleEngineSkiaMessage(fml::RefPtr<PlatformMessage> message); |
|||
|
|||
// |Engine::Delegate| |
|||
void OnPreEngineRestart() override; |
|||
|
|||
// |Engine::Delegate| |
|||
void UpdateIsolateDescription(const std::string isolate_name, |
|||
int64_t isolate_port) override; |
|||
|
|||
// |Engine::Delegate| |
|||
void SetNeedsReportTimings(bool value) override; |
|||
|
|||
// |Rasterizer::Delegate| |
|||
void OnFrameRasterized(const FrameTiming&) override; |
|||
|
|||
// |Rasterizer::Delegate| |
|||
fml::Milliseconds GetFrameBudget() override; |
|||
|
|||
// |ServiceProtocol::Handler| |
|||
fml::RefPtr<fml::TaskRunner> GetServiceProtocolHandlerTaskRunner( |
|||
std::string_view method) const override; |
|||
|
|||
// |ServiceProtocol::Handler| |
|||
bool HandleServiceProtocolMessage( |
|||
std::string_view method, // one if the extension names specified above. |
|||
const ServiceProtocolMap& params, |
|||
rapidjson::Document& response) override; |
|||
|
|||
// |ServiceProtocol::Handler| |
|||
ServiceProtocol::Handler::Description GetServiceProtocolDescription() |
|||
const override; |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolScreenshot( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolScreenshotSKP( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolRunInView( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolFlushUIThreadTasks( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolSetAssetBundlePath( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
bool OnServiceProtocolGetDisplayRefreshRate( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
// Service protocol handler |
|||
// |
|||
// The returned SkSLs are base64 encoded. Decode before storing them to files. |
|||
bool OnServiceProtocolGetSkSLs( |
|||
const ServiceProtocol::Handler::ServiceProtocolMap& params, |
|||
rapidjson::Document& response); |
|||
|
|||
fml::WeakPtrFactory<Shell> weak_factory_; |
|||
|
|||
// For accessing the Shell via the raster thread, necessary for various |
|||
// rasterizer callbacks. |
|||
std::unique_ptr<fml::WeakPtrFactory<Shell>> weak_factory_gpu_; |
|||
|
|||
friend class testing::ShellTest; |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(Shell); |
|||
}; |
|||
|
|||
} // namespace flutter |
|||
|
|||
#endif // SHELL_COMMON_SHELL_H_ |
|
|||
#include "scene.h"
|
|||
|
|||
#include "flutter/fml/trace_event.h"
|
|||
#include "lib/ui/painting/image.h"
|
|||
#include "lib/ui/painting/picture.h"
|
|||
#include "lib/ui/ui_mono_state.h"
|
|||
#include "lib/ui/window/window.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
fml::RefPtr<Scene> Scene::create(std::shared_ptr<Layer> rootLayer, |
|||
uint32_t rasterizerTracingThreshold, |
|||
bool checkerboardRasterCacheImages, |
|||
bool checkerboardOffscreenLayers) { |
|||
return fml::MakeRefCounted<Scene>( |
|||
std::move(rootLayer), rasterizerTracingThreshold, |
|||
checkerboardRasterCacheImages, checkerboardOffscreenLayers); |
|||
} |
|||
|
|||
Scene::Scene(std::shared_ptr<Layer> rootLayer, |
|||
uint32_t rasterizerTracingThreshold, |
|||
bool checkerboardRasterCacheImages, |
|||
bool checkerboardOffscreenLayers) { |
|||
auto viewport_metrics = UIMonoState::Current()->window()->viewport_metrics(); |
|||
|
|||
layer_tree_ = std::make_unique<LayerTree>( |
|||
SkISize::Make(viewport_metrics.physical_width, |
|||
viewport_metrics.physical_height), |
|||
static_cast<float>(viewport_metrics.physical_depth), |
|||
static_cast<float>(viewport_metrics.device_pixel_ratio)); |
|||
layer_tree_->set_root_layer(std::move(rootLayer)); |
|||
layer_tree_->set_rasterizer_tracing_threshold(rasterizerTracingThreshold); |
|||
layer_tree_->set_checkerboard_raster_cache_images( |
|||
checkerboardRasterCacheImages); |
|||
layer_tree_->set_checkerboard_offscreen_layers(checkerboardOffscreenLayers); |
|||
} |
|||
|
|||
Scene::~Scene() {} |
|||
|
|||
void Scene::dispose() {} |
|||
|
|||
const char* Scene::toImage(uint32_t width, uint32_t height, |
|||
Picture::RawImageCallback raw_image_callback, |
|||
Mono_Handle callback_handle) { |
|||
TRACE_EVENT0("uiwidgets", "Scene::toImage"); |
|||
|
|||
if (!layer_tree_) { |
|||
return "Scene did not contain a layer tree."; |
|||
} |
|||
|
|||
auto picture = layer_tree_->Flatten(SkRect::MakeWH(width, height)); |
|||
if (!picture) { |
|||
return "Could not flatten scene into a layer tree."; |
|||
} |
|||
|
|||
return Picture::RasterizeToImage(picture, width, height, raw_image_callback, |
|||
callback_handle); |
|||
} |
|||
|
|||
std::unique_ptr<LayerTree> Scene::takeLayerTree() { |
|||
return std::move(layer_tree_); |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#include <memory> |
|||
|
|||
#include "flow/layers/layer_tree.h" |
|||
#include "lib/ui/painting/picture.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class Scene : public fml::RefCountedThreadSafe<Scene> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(Scene); |
|||
|
|||
public: |
|||
~Scene(); |
|||
static fml::RefPtr<Scene> create(std::shared_ptr<Layer> rootLayer, |
|||
uint32_t rasterizerTracingThreshold, |
|||
bool checkerboardRasterCacheImages, |
|||
bool checkerboardOffscreenLayers); |
|||
|
|||
std::unique_ptr<LayerTree> takeLayerTree(); |
|||
|
|||
const char* toImage(uint32_t width, uint32_t height, |
|||
Picture::RawImageCallback raw_image_callback, |
|||
Mono_Handle callback_handle); |
|||
|
|||
void dispose(); |
|||
|
|||
private: |
|||
explicit Scene(std::shared_ptr<Layer> rootLayer, |
|||
uint32_t rasterizerTracingThreshold, |
|||
bool checkerboardRasterCacheImages, |
|||
bool checkerboardOffscreenLayers); |
|||
|
|||
std::unique_ptr<LayerTree> layer_tree_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|
|||
|
|||
#include "scene_builder.h"
|
|||
|
|||
#include "flow/layers/backdrop_filter_layer.h"
|
|||
#include "flow/layers/clip_path_layer.h"
|
|||
#include "flow/layers/clip_rect_layer.h"
|
|||
#include "flow/layers/clip_rrect_layer.h"
|
|||
#include "flow/layers/color_filter_layer.h"
|
|||
#include "flow/layers/container_layer.h"
|
|||
#include "flow/layers/image_filter_layer.h"
|
|||
#include "flow/layers/layer.h"
|
|||
#include "flow/layers/layer_tree.h"
|
|||
#include "flow/layers/opacity_layer.h"
|
|||
#include "flow/layers/performance_overlay_layer.h"
|
|||
#include "flow/layers/physical_shape_layer.h"
|
|||
#include "flow/layers/picture_layer.h"
|
|||
#include "flow/layers/platform_view_layer.h"
|
|||
#include "flow/layers/shader_mask_layer.h"
|
|||
#include "flow/layers/texture_layer.h"
|
|||
#include "flow/layers/transform_layer.h"
|
|||
#include "include/core/SkColorFilter.h"
|
|||
#include "lib/ui/painting/matrix.h"
|
|||
#include "lib/ui/painting/shader.h"
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
SceneBuilder::SceneBuilder() { PushLayer(std::make_shared<ContainerLayer>()); } |
|||
|
|||
SceneBuilder::~SceneBuilder() = default; |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushTransform(float* matrix4) { |
|||
SkMatrix sk_matrix = ToSkMatrix(matrix4); |
|||
auto layer = std::make_shared<TransformLayer>(sk_matrix); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushOffset(float dx, float dy) { |
|||
SkMatrix sk_matrix = SkMatrix::Translate(dx, dy); |
|||
auto layer = std::make_shared<TransformLayer>(sk_matrix); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushClipRect(float left, float right, |
|||
float top, float bottom, |
|||
int clipBehavior) { |
|||
SkRect clipRect = SkRect::MakeLTRB(left, top, right, bottom); |
|||
Clip clip_behavior = static_cast<Clip>(clipBehavior); |
|||
auto layer = std::make_shared<ClipRectLayer>(clipRect, clip_behavior); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushClipRRect(const RRect& rrect, |
|||
int clipBehavior) { |
|||
Clip clip_behavior = static_cast<Clip>(clipBehavior); |
|||
auto layer = std::make_shared<ClipRRectLayer>(rrect.sk_rrect, clip_behavior); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushClipPath(const CanvasPath* path, |
|||
int clipBehavior) { |
|||
Clip clip_behavior = static_cast<Clip>(clipBehavior); |
|||
FML_DCHECK(clip_behavior != Clip::none); |
|||
auto layer = std::make_shared<ClipPathLayer>(path->path(), clip_behavior); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushOpacity(int alpha, float dx, |
|||
float dy) { |
|||
auto layer = std::make_shared<OpacityLayer>(alpha, SkPoint::Make(dx, dy)); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushColorFilter( |
|||
|
|||
const ColorFilter* color_filter) { |
|||
auto layer = std::make_shared<ColorFilterLayer>(color_filter->filter()); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushImageFilter( |
|||
const ImageFilter* image_filter) { |
|||
auto layer = std::make_shared<ImageFilterLayer>(image_filter->filter()); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushBackdropFilter(ImageFilter* filter) { |
|||
auto layer = std::make_shared<BackdropFilterLayer>(filter->filter()); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushShaderMask( |
|||
Shader* shader, float maskRectLeft, float maskRectRight, float maskRectTop, |
|||
float maskRectBottom, int blendMode) { |
|||
SkRect rect = SkRect::MakeLTRB(maskRectLeft, maskRectTop, maskRectRight, |
|||
maskRectBottom); |
|||
auto layer = std::make_shared<ShaderMaskLayer>( |
|||
shader->shader(), rect, static_cast<SkBlendMode>(blendMode)); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
fml::RefPtr<EngineLayer> SceneBuilder::pushPhysicalShape(const CanvasPath* path, |
|||
float elevation, |
|||
int color, |
|||
int shadow_color, |
|||
int clipBehavior) { |
|||
auto layer = std::make_shared<PhysicalShapeLayer>( |
|||
static_cast<SkColor>(color), static_cast<SkColor>(shadow_color), |
|||
static_cast<float>(elevation), path->path(), |
|||
static_cast<Clip>(clipBehavior)); |
|||
PushLayer(layer); |
|||
return EngineLayer::MakeRetained(layer); |
|||
} |
|||
|
|||
void SceneBuilder::addRetained(fml::RefPtr<EngineLayer> retainedLayer) { |
|||
AddLayer(retainedLayer->Layer()); |
|||
} |
|||
|
|||
void SceneBuilder::pop() { PopLayer(); } |
|||
|
|||
void SceneBuilder::addPicture(float dx, float dy, Picture* picture, int hints) { |
|||
SkPoint offset = SkPoint::Make(dx, dy); |
|||
SkRect pictureRect = picture->picture()->cullRect(); |
|||
pictureRect.offset(offset.x(), offset.y()); |
|||
auto layer = std::make_unique<PictureLayer>( |
|||
offset, UIMonoState::CreateGPUObject(picture->picture()), !!(hints & 1), |
|||
!!(hints & 2)); |
|||
AddLayer(std::move(layer)); |
|||
} |
|||
|
|||
void SceneBuilder::addTexture(float dx, float dy, float width, float height, |
|||
int64_t textureId, bool freeze) { |
|||
auto layer = std::make_unique<TextureLayer>( |
|||
SkPoint::Make(dx, dy), SkSize::Make(width, height), textureId, freeze); |
|||
AddLayer(std::move(layer)); |
|||
} |
|||
|
|||
void SceneBuilder::addPlatformView(float dx, float dy, float width, |
|||
float height, int64_t viewId) { |
|||
auto layer = std::make_unique<PlatformViewLayer>( |
|||
SkPoint::Make(dx, dy), SkSize::Make(width, height), viewId); |
|||
AddLayer(std::move(layer)); |
|||
} |
|||
|
|||
void SceneBuilder::addPerformanceOverlay(uint64_t enabledOptions, float left, |
|||
float right, float top, float bottom) { |
|||
SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); |
|||
auto layer = std::make_unique<PerformanceOverlayLayer>(enabledOptions); |
|||
layer->set_paint_bounds(rect); |
|||
AddLayer(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<Scene> SceneBuilder::build() { |
|||
FML_DCHECK(layer_stack_.size() >= 1); |
|||
|
|||
return Scene::create(layer_stack_[0], rasterizer_tracing_threshold_, |
|||
checkerboard_raster_cache_images_, |
|||
checkerboard_offscreen_layers_); |
|||
} |
|||
|
|||
void SceneBuilder::AddLayer(std::shared_ptr<Layer> layer) { |
|||
FML_DCHECK(layer); |
|||
|
|||
if (!layer_stack_.empty()) { |
|||
layer_stack_.back()->Add(std::move(layer)); |
|||
} |
|||
} |
|||
|
|||
void SceneBuilder::PushLayer(std::shared_ptr<ContainerLayer> layer) { |
|||
AddLayer(layer); |
|||
layer_stack_.push_back(std::move(layer)); |
|||
} |
|||
|
|||
void SceneBuilder::PopLayer() { |
|||
// We never pop the root layer, so that AddLayer operations are always valid.
|
|||
if (layer_stack_.size() > 1) { |
|||
layer_stack_.pop_back(); |
|||
} |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
#pragma once |
|||
|
|||
#include <stdint.h> |
|||
|
|||
#include <memory> |
|||
#include <vector> |
|||
|
|||
#include "flow/layers/container_layer.h" |
|||
#include "lib/ui/compositing/scene.h" |
|||
#include "lib/ui/painting/color_filter.h" |
|||
#include "lib/ui/painting/engine_layer.h" |
|||
#include "lib/ui/painting/image_filter.h" |
|||
#include "lib/ui/painting/path.h" |
|||
#include "lib/ui/painting/picture.h" |
|||
#include "lib/ui/painting/rrect.h" |
|||
#include "lib/ui/painting/shader.h" |
|||
|
|||
namespace uiwidgets { |
|||
|
|||
class SceneBuilder : public fml::RefCountedThreadSafe<SceneBuilder> { |
|||
FML_FRIEND_MAKE_REF_COUNTED(SceneBuilder); |
|||
|
|||
public: |
|||
static fml::RefPtr<SceneBuilder> create() { |
|||
return fml::MakeRefCounted<SceneBuilder>(); |
|||
} |
|||
~SceneBuilder(); |
|||
|
|||
fml::RefPtr<EngineLayer> pushTransform(float* matrix4); |
|||
|
|||
fml::RefPtr<EngineLayer> pushOffset(float dx, float dy); |
|||
fml::RefPtr<EngineLayer> pushClipRect(float left, float right, float top, |
|||
float bottom, int clipBehavior); |
|||
fml::RefPtr<EngineLayer> pushClipRRect(const RRect& rrect, int clipBehavior); |
|||
fml::RefPtr<EngineLayer> pushClipPath(const CanvasPath* path, |
|||
int clipBehavior); |
|||
fml::RefPtr<EngineLayer> pushOpacity(int alpha, float dx = 0, float dy = 0); |
|||
fml::RefPtr<EngineLayer> pushColorFilter(const ColorFilter* color_filter); |
|||
fml::RefPtr<EngineLayer> pushImageFilter(const ImageFilter* image_filter); |
|||
fml::RefPtr<EngineLayer> pushBackdropFilter(ImageFilter* filter); |
|||
fml::RefPtr<EngineLayer> pushShaderMask(Shader* shader, float maskRectLeft, |
|||
float maskRectRight, |
|||
float maskRectTop, |
|||
float maskRectBottom, int blendMode); |
|||
fml::RefPtr<EngineLayer> pushPhysicalShape(const CanvasPath* path, |
|||
float elevation, int color, |
|||
int shadowColor, int clipBehavior); |
|||
|
|||
void addRetained(fml::RefPtr<EngineLayer> retainedLayer); |
|||
|
|||
void pop(); |
|||
|
|||
void addPerformanceOverlay(uint64_t enabledOptions, float left, float right, |
|||
float top, float bottom); |
|||
|
|||
void addPicture(float dx, float dy, Picture* picture, int hints); |
|||
|
|||
void addTexture(float dx, float dy, float width, float height, |
|||
int64_t textureId, bool freeze); |
|||
|
|||
void addPlatformView(float dx, float dy, float width, float height, |
|||
int64_t viewId); |
|||
|
|||
void setRasterizerTracingThreshold(uint32_t frameInterval); |
|||
void setCheckerboardRasterCacheImages(bool checkerboard); |
|||
void setCheckerboardOffscreenLayers(bool checkerboard); |
|||
|
|||
fml::RefPtr<Scene> build(); |
|||
|
|||
private: |
|||
SceneBuilder(); |
|||
|
|||
void AddLayer(std::shared_ptr<Layer> layer); |
|||
void PushLayer(std::shared_ptr<ContainerLayer> layer); |
|||
void PopLayer(); |
|||
|
|||
std::vector<std::shared_ptr<ContainerLayer>> layer_stack_; |
|||
int rasterizer_tracing_threshold_ = 0; |
|||
bool checkerboard_raster_cache_images_ = false; |
|||
bool checkerboard_offscreen_layers_ = false; |
|||
|
|||
FML_DISALLOW_COPY_AND_ASSIGN(SceneBuilder); |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
撰写
预览
正在加载...
取消
保存
Reference in new issue