浏览代码

Merge branch 'master' of gitlab.cds.internal.unity3d.com:upm-packages/ui-widgets/com.unity.uiwidgets into material

/main
xingwei.zhu 6 年前
当前提交
fc02e20d
共有 36 个文件被更改,包括 1152 次插入545 次删除
  1. 110
      Editor/editor/EditorUtils.cs
  2. 12
      README.md
  3. 2
      Runtime/Plugins/DeviceScreen.mm
  4. 2
      Runtime/Resources/UIWidgets_canvas.cginc
  5. 47
      Runtime/engine/DisplayMetrics.cs
  6. 20
      Runtime/engine/WidgetCanvas.cs
  7. 26
      Runtime/flow/clip_rect_layer.cs
  8. 27
      Runtime/flow/clip_rrect_layer.cs
  9. 2
      Runtime/flow/compositor_context.cs
  10. 10
      Runtime/flow/container_layer.cs
  11. 16
      Runtime/flow/layer.cs
  12. 10
      Runtime/flow/layer_tree.cs
  13. 31
      Runtime/flow/opacity_layer.cs
  14. 28
      Runtime/flow/picture_layer.cs
  15. 31
      Runtime/flow/transform_layer.cs
  16. 4
      Runtime/gestures/binding.cs
  17. 7
      Runtime/gestures/converter.cs
  18. 4
      Runtime/painting/borders.cs
  19. 2
      Runtime/promise.meta
  20. 1
      Runtime/rendering/box.mixin.gen.cs
  21. 372
      Runtime/rendering/layer.cs
  22. 8
      Runtime/rendering/proxy_box.mixin.njk
  23. 2
      Runtime/rendering/view.cs
  24. 47
      Runtime/ui/compositing.cs
  25. 8
      Runtime/ui/geometry.cs
  26. 10
      Runtime/ui/painting/canvas.cs
  27. 21
      Runtime/ui/painting/canvas_clip.cs
  28. 562
      Runtime/ui/painting/canvas_impl.cs
  29. 54
      Runtime/ui/painting/canvas_shader.cs
  30. 47
      Runtime/ui/painting/path.cs
  31. 74
      Runtime/ui/painting/picture.cs
  32. 2
      Runtime/ui/txt/layout.cs
  33. 34
      Runtime/ui/txt/linebreaker.cs
  34. 7
      Runtime/widgets/widget_inspector.cs
  35. 46
      Runtime/flow/clip_path_layer.cs
  36. 11
      Runtime/flow/clip_path_layer.cs.meta

110
Editor/editor/EditorUtils.cs


using System;
using System.Collections;
using System.Reflection;
using UnityEngine;
public class Startup {
static Startup() {
DisplayMetrics.SetDevicePixelRatioGetter(() => { return EditorGUIUtility.pixelsPerPoint; });
public class EitorUtils {
static EitorUtils() {
DisplayMetricsProvider.provider = () => new EditorPlayerDisplayMetrics();
}
}
public class EditorPlayerDisplayMetrics : DisplayMetrics {
float _lastDevicePixelRatio = 0;
public void OnGUI() {
}
public void Update() {
this._lastDevicePixelRatio = GameViewUtil.getGameViewDevicePixelRatio();
}
public float DevicePixelRatio {
get { return this._lastDevicePixelRatio; }
}
}
internal static class GameViewUtil {
static Type _gameViewType;
static string _gameViewClassName = "UnityEditor.GameView";
public static float getGameViewDevicePixelRatio(float fallback = 1) {
loadTypeIfNeed();
EditorWindow gameview = getMainGameView();
if (gameview == null) {
return fallback;
}
bool lowResolutionForAspectRatios = false;
if (!getPropertyValue(gameview, "lowResolutionForAspectRatios",
ref lowResolutionForAspectRatios)) {
return fallback;
}
if (lowResolutionForAspectRatios) {
return 1;
}
Vector2 sizeValue = new Vector2();
if (!getFieldValue(gameview, "m_LastWindowPixelSize", ref sizeValue)) {
return fallback;
}
if (gameview.position.width > 0) {
return sizeValue.x / gameview.position.width;
}
if (gameview.position.height > 0) {
return sizeValue.y / gameview.position.height;
}
return fallback;
}
static EditorWindow getMainGameView() {
IEnumerable enumerable = null;
if (!getFieldValue(null, "s_GameViews", ref enumerable)) {
return null;
}
IEnumerator enumerator = enumerable != null ? enumerable.GetEnumerator() : null;
if (enumerator != null && enumerator.MoveNext()) {
return enumerator.Current as EditorWindow;
}
return null;
}
static bool getFieldValue<T>(object ins, string name, ref T result) {
var fieldInfo = _gameViewType.GetField(name, BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Static | BindingFlags.Instance);
if (fieldInfo == null) {
return false;
}
result = (T)fieldInfo.GetValue(ins);
return true;
}
static void loadTypeIfNeed() {
if (_gameViewType == null) {
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) {
var type = assembly.GetType(_gameViewClassName);
if (type != null) {
_gameViewType = type;
}
}
}
}
static bool getPropertyValue<T>(object ins, string name, ref T result) {
var property = _gameViewType.GetProperty(name, BindingFlags.Public
| BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance);
if (property == null) {
return false;
}
result = (T) property.GetValue(ins);
return true;
}
}
}

12
README.md


3. **Refine Code Style Rules**: Edit the ".editorconfig" file under \<YourProjectPath\>/Packages/com.unity.uiwidgets/". Visit
https://www.jetbrains.com/help/rider/EditorConfig_Index.html for the detailed.
#### Generate njk Code
1. **Go to scripts Folder and Run npm install**:
```
cd <YourProjectPath>/Packages/com.unity.uiwidgets/scripts
npm install
```
2. **Run the codegen Command**:
```
node uiwidgets-cli.js codegen . generate mixin code
```

2
Runtime/Plugins/DeviceScreen.mm


#import <UIKit/UIKit.h>
extern "C"
{
int IOSDeviceSaleFactor()
int IOSDeviceScaleFactor()
{
return [[UIScreen mainScreen] scale];
}

2
Runtime/Resources/UIWidgets_canvas.cginc


float3x3 mat = float3x3(_mat[0], _mat[1], _mat[2], _mat[3], _mat[4], _mat[5], 0, 0, 1);
half2 p = mul(mat, half3(v.vertex.xy, 1.0)).xy - _viewport.xy;
float2 p = mul(mat, float3(v.vertex.xy, 1.0)).xy - _viewport.xy;
#if UNITY_UV_STARTS_AT_TOP
o.vertex = float4(2.0 * p.x / _viewport.z - 1.0, 2.0 * p.y / _viewport.w - 1.0, 0, 1);

47
Runtime/engine/DisplayMetrics.cs


using System;
using System.Runtime.InteropServices;
using UnityEngine;
public class DisplayMetrics {
static float _devicePixelRatio = 0;
static Func<float> _devicePixelRatioGetter;
public static class DisplayMetricsProvider {
public static Func<DisplayMetrics> provider = () => new PlayerDisplayMetrics();
}
public interface DisplayMetrics {
void OnGUI();
void Update();
public static void SetDevicePixelRatioGetter(Func<float> f) {
_devicePixelRatioGetter = f;
float DevicePixelRatio { get; }
}
public class PlayerDisplayMetrics: DisplayMetrics {
float _devicePixelRatio = 0;
public void OnGUI() {
}
public void Update() {
public static float devicePixelRatio {
public float DevicePixelRatio {
if (_devicePixelRatioGetter != null) {
return _devicePixelRatioGetter();
}
if (_devicePixelRatio > 0) {
return _devicePixelRatio;
if (this._devicePixelRatio > 0) {
return this._devicePixelRatio;
}
#if UNITY_ANDROID

#endif
#if UNITY_IOS
_devicePixelRatio = IOSDeviceSaleFactor();
_devicePixelRatio = IOSDeviceScaleFactor();
if (_devicePixelRatio <= 0) {
_devicePixelRatio = 1;
if (this._devicePixelRatio <= 0) {
this._devicePixelRatio = 1;
return _devicePixelRatio;
return this._devicePixelRatio;
}
}

#if UNITY_IOS
[DllImport("__Internal")]
static extern int IOSDeviceSaleFactor();
static extern int IOSDeviceScaleFactor();
#endif
}

20
Runtime/engine/WidgetCanvas.cs


}
protected override Vector2 queryWindowSize() {
var size = this._widgetCanvas.rectTransform.rect.size;
size = size * this._widgetCanvas.canvas.scaleFactor / this._widgetCanvas.devicePixelRatio;
return new Vector2(Mathf.Round(size.x), Mathf.Round(size.y));
var rect = RectTransformUtility.PixelAdjustRect(this._widgetCanvas.rectTransform,
this._widgetCanvas.canvas);
var size = new Vector2(rect.width, rect.height) / this._widgetCanvas.devicePixelRatio;
size.x = Mathf.Round(size.x);
size.y = Mathf.Round(size.y);
return size;
}
}

static Event _repaintEvent;
[SerializeField] protected float devicePixelRatioOverride;
WindowAdapter _windowAdapter;
Texture _texture;
Vector2 _lastMouseMove;

const int mouseScrollId = mouseButtonNum + 1;
readonly ScrollInput _scrollInput = new ScrollInput();
DisplayMetrics _displayMetrics;
this._displayMetrics = DisplayMetricsProvider.provider();
Input.simulateMouseWithTouches = false;

get {
return this.devicePixelRatioOverride > 0
? this.devicePixelRatioOverride
: DisplayMetrics.devicePixelRatio;
: this._displayMetrics.DevicePixelRatio;
}
}

this.texture = texture;
this.material = mat;
}
this._displayMetrics.Update();
if (EventSystem.current != null && EventSystem.current.currentSelectedGameObject != this.gameObject) {
this.unfocusIfNeeded();
}

}
void OnGUI() {
this._displayMetrics.OnGUI();
if (Event.current.type == EventType.KeyDown || Event.current.type == EventType.KeyUp) {
this._windowAdapter.OnGUI(Event.current);
}

26
Runtime/flow/clip_rect_layer.cs


using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.flow {
public class ClipRectLayer : ContainerLayer {

}
public override void preroll(PrerollContext context, Matrix3 matrix) {
var childPaintBounds = Rect.zero;
this.prerollChildren(context, matrix, ref childPaintBounds);
childPaintBounds = childPaintBounds.intersect(this._clipRect);
var previousCullRect = context.cullRect;
if (!childPaintBounds.isEmpty) {
this.paintBounds = childPaintBounds;
context.cullRect = context.cullRect.intersect(this._clipRect);
if (!context.cullRect.isEmpty) {
var childPaintBounds = Rect.zero;
this.prerollChildren(context, matrix, ref childPaintBounds);
childPaintBounds = childPaintBounds.intersect(this._clipRect);
if (!childPaintBounds.isEmpty) {
this.paintBounds = childPaintBounds;
}
context.cullRect = previousCullRect;
D.assert(this.needsPainting);
var canvas = context.canvas;
canvas.save();

this.paintChildren(context);
}
finally {
} finally {
canvas.restore();
}
}

27
Runtime/flow/clip_rrect_layer.cs


using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.flow {
public class ClipRRectLayer : ContainerLayer {

}
public override void preroll(PrerollContext context, Matrix3 matrix) {
var childPaintBounds = Rect.zero;
this.prerollChildren(context, matrix, ref childPaintBounds);
childPaintBounds = childPaintBounds.intersect(this._clipRRect.outerRect);
var previousCullRect = context.cullRect;
var clipPathBounds = this._clipRRect.outerRect;
context.cullRect = context.cullRect.intersect(clipPathBounds);
if (!context.cullRect.isEmpty) {
var childPaintBounds = Rect.zero;
this.prerollChildren(context, matrix, ref childPaintBounds);
childPaintBounds = childPaintBounds.intersect(clipPathBounds);
if (!childPaintBounds.isEmpty) {
this.paintBounds = childPaintBounds;
if (!childPaintBounds.isEmpty) {
this.paintBounds = childPaintBounds;
}
context.cullRect = previousCullRect;
D.assert(this.needsPainting);
var canvas = context.canvas;
canvas.save();

this.paintChildren(context);
}
finally {
} finally {
canvas.restore();
}
}

2
Runtime/flow/compositor_context.cs


public bool raster(LayerTree layerTree, bool ignoreRasterCache) {
layerTree.preroll(this, ignoreRasterCache);
layerTree.paint(this);
layerTree.paint(this, ignoreRasterCache);
return true;
}

10
Runtime/flow/container_layer.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.flow {

protected void prerollChildren(PrerollContext context, Matrix3 childMatrix, ref Rect childPaintBounds) {
foreach (var layer in this._layers) {
layer.preroll(context, childMatrix);
childPaintBounds = childPaintBounds.expandToInclude(layer.paintBounds);
if (childPaintBounds == null || childPaintBounds.isEmpty) {
childPaintBounds = layer.paintBounds;
} else {
childPaintBounds = childPaintBounds.expandToInclude(layer.paintBounds);
}
D.assert(this.needsPainting);
foreach (var layer in this._layers) {
if (layer.needsPainting) {
layer.paint(context);

16
Runtime/flow/layer.cs


public class PrerollContext {
public RasterCache rasterCache;
public float devicePixelRatio;
public Rect cullRect;
public RasterCache rasterCache;
}
public abstract class Layer {

public Rect paintBounds {
get { return this._paintBounds; }
set { this._paintBounds = value; }
set { this._paintBounds = value ?? Rect.zero; }
}
public bool needsPainting {

}
public abstract void paint(PaintContext context);
}
static class LayerUtils {
public static void alignToPixel(this Canvas canvas) {
var matrix = canvas.getTotalMatrix();
var devicePixelRatio = canvas.getDevicePixelRatio();
var x = matrix[2].alignToPixel(devicePixelRatio);
var y = matrix[5].alignToPixel(devicePixelRatio);
if (x != matrix[2] || y != matrix[5]) {
canvas.translate(x - matrix[2], y - matrix[5]);
}
}
}
}

10
Runtime/flow/layer_tree.cs


set { this._devicePixelRatio = value; }
}
static readonly Matrix3 _identityMatrix = Matrix3.I();
devicePixelRatio = frame.canvas().getDevicePixelRatio()
devicePixelRatio = frame.canvas().getDevicePixelRatio(),
cullRect = Rect.largest,
this._rootLayer.preroll(prerollContext, Matrix3.I());
this._rootLayer.preroll(prerollContext, _identityMatrix);
public void paint(CompositorContext.ScopedFrame frame) {
public void paint(CompositorContext.ScopedFrame frame, bool ignoreRasterCache = false) {
rasterCache = ignoreRasterCache ? null : frame.context().rasterCache(),
};
if (this._rootLayer.needsPainting) {

31
Runtime/flow/opacity_layer.cs


using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
Offset _offset;
public Offset offset {
set { this._offset = value; }
}
int _alpha;
public int alpha {

public override void preroll(PrerollContext context, Matrix3 matrix) {
var childMatrix = new Matrix3(matrix);
childMatrix.postTranslate(this._offset.dx, this._offset.dy); // TOOD: pre or post? https://github.com/flutter/engine/pull/7945
base.preroll(context, childMatrix);
var bounds = this.paintBounds.shift(this._offset);
this.paintBounds = bounds;
}
D.assert(this.needsPainting);
canvas.save();
canvas.translate(this._offset.dx, this._offset.dy);
canvas.alignToPixel();
var saveLayerBounds = this.paintBounds.shift(-this._offset).roundOut();
canvas.saveLayer(this.paintBounds, paint);
canvas.saveLayer(saveLayerBounds, paint);
canvas.restore();
canvas.restore();
}
}

28
Runtime/flow/picture_layer.cs


using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
Offset _offset;
Offset _offset = Offset.zero;
set { this._offset = value; }
set { this._offset = value ?? Offset.zero; }
}
Picture _picture;

public override void preroll(PrerollContext context, Matrix3 matrix) {
if (context.rasterCache != null) {
Matrix3 ctm = new Matrix3(matrix);
ctm.postTranslate(this._offset.dx, this._offset.dy);
ctm.postTranslate(this._offset.dx, this._offset.dy); // TOOD: pre or post? https://github.com/flutter/engine/pull/7945
}
else {
} else {
this._rasterCacheResult = null;
}

public override void paint(PaintContext context) {
D.assert(this._picture != null);
D.assert(this.needsPainting);
// align to pixel
var matrix = canvas.getTotalMatrix();
var devicePixelRatio = context.canvas.getDevicePixelRatio();
matrix[2] = matrix[2].alignToPixel(devicePixelRatio);
matrix[5] = matrix[5].alignToPixel(devicePixelRatio);
canvas.setMatrix(matrix);
canvas.alignToPixel();
}
else {
} else {
}
finally {
} finally {
canvas.restore();
}
}

31
Runtime/flow/transform_layer.cs


using Unity.UIWidgets.ui;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
Matrix3 _tranform;
Matrix3 _transform;
set { this._tranform = value; }
set { this._transform = value; }
var childMatrix = Matrix3.concat(this._tranform, matrix);
var childMatrix = Matrix3.concat(matrix, this._transform);
var previousCullRect = context.cullRect;
Matrix3 inverseTransform = Matrix3.I();
if (this._transform.invert(inverseTransform)) {
context.cullRect = inverseTransform.mapRect(context.cullRect);
} else {
context.cullRect = Rect.largest;
}
childPaintBounds = this._tranform.mapRect(childPaintBounds);
childPaintBounds = this._transform.mapRect(childPaintBounds);
context.cullRect = previousCullRect;
D.assert(this.needsPainting);
canvas.concat(this._tranform);
canvas.concat(this._transform);
}
finally {
} finally {
}
}

4
Runtime/gestures/binding.cs


});
}
else if (evt is PointerUpEvent || evt is PointerCancelEvent) {
result = this._hitTests[evt.pointer];
result = this._hitTests.getOrDefault(evt.pointer);
result = this._hitTests[evt.pointer];
result = this._hitTests.getOrDefault(evt.pointer);
}
else {
return;

7
Runtime/gestures/converter.cs


case PointerChange.up:
case PointerChange.cancel: {
D.assert(_pointers.ContainsKey(datum.device));
_PointerState state = _pointers[datum.device];
_PointerState state = _pointers.getOrDefault(datum.device);
if (state == null || !state.down) {
break;
}
D.assert(state.down);
if (position != state.lastPosition) {
Offset offset = position - state.lastPosition;

4
Runtime/painting/borders.cs


public readonly float width;
public readonly BorderStyle style;
public static readonly BorderSide none = new BorderSide(width: 0.0f);
public static readonly BorderSide none = new BorderSide(width: 0.0f, style: BorderStyle.none);
public BorderSide copyWith(
Color color = null,

case BorderStyle.none:
break;
}
switch (left.style) {
case BorderStyle.solid:
Paint paint = new Paint {

2
Runtime/promise.meta


fileFormatVersion: 2
guid: e2adb93c961cc4d4e8d94fce276c0b57
guid: bec4d0b4a41b94eb49b1912f962f12fc
folderAsset: yes
DefaultImporter:
externalObjects: {}

1
Runtime/rendering/box.mixin.gen.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.ui;

372
Runtime/rendering/layer.cs


get { return (ContainerLayer) base.parent; }
}
bool _needsAddToScene = true;
protected void markNeedsAddToScene() {
this._needsAddToScene = true;
}
protected virtual bool alwaysNeedsAddToScene {
get { return false; }
}
internal bool _subtreeNeedsAddToScene;
flow.Layer _engineLayer;
internal virtual void updateSubtreeNeedsAddToScene() {
this._subtreeNeedsAddToScene = this._needsAddToScene || this.alwaysNeedsAddToScene;
}
public Layer nextSibling {
get { return this._nextSibling; }
}

internal Layer _previousSibling;
protected override void dropChild(AbstractNodeMixinDiagnosticableTree child) {
this.markNeedsAddToScene();
base.dropChild(child);
}
protected override void adoptChild(AbstractNodeMixinDiagnosticableTree child) {
this.markNeedsAddToScene();
base.adoptChild(child);
}
public virtual void remove() {
if (this.parent != null) {
this.parent._removeChild(this);

D.assert(!this.attached);
}
public abstract void addToScene(SceneBuilder builder, Offset layerOffset);
internal abstract flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null);
internal void _addToSceneWithRetainedRendering(SceneBuilder builder) {
if (!this._subtreeNeedsAddToScene && this._engineLayer != null) {
builder.addRetained(this._engineLayer);
return;
}
this._engineLayer = this.addToScene(builder);
this._needsAddToScene = false;
}
return base.toStringShort() + (this.owner == null ? "DETACHED" : "");
return base.toStringShort() + (this.owner == null ? " DETACHED" : "");
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

public readonly Rect canvasBounds;
public Picture picture;
Picture _picture;
public Picture picture {
get { return this._picture; }
set {
this.markNeedsAddToScene();
this._picture = value;
}
}
public bool isComplexHint = false;
bool _isComplexHint = false;
public bool isComplexHint {
get { return this._isComplexHint; }
set {
if (value != this._isComplexHint) {
this._isComplexHint = value;
this.markNeedsAddToScene();
}
}
}
public bool willChangeHint = false;
bool _willChangeHint = false;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
public bool willChangeHint {
get { return this._willChangeHint; }
set {
if (value != this._willChangeHint) {
this._willChangeHint = value;
this.markNeedsAddToScene();
}
}
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
isComplex: this.isComplexHint, willChange: this.willChangeHint);
isComplexHint: this.isComplexHint, willChangeHint: this.willChangeHint);
return null;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

}
return child == equals;
}
internal override void updateSubtreeNeedsAddToScene() {
base.updateSubtreeNeedsAddToScene();
Layer child = this.firstChild;
while (child != null) {
child.updateSubtreeNeedsAddToScene();
this._subtreeNeedsAddToScene = this._subtreeNeedsAddToScene || child._subtreeNeedsAddToScene;
child = child.nextSibling;
}
}
public override void attach(object owner) {

D.assert(child.attached == this.attached);
}
public void _removeChild(Layer child) {
internal void _removeChild(Layer child) {
D.assert(child.parent == this);
D.assert(child.attached == this.attached);
D.assert(this._debugUltimatePreviousSiblingOf(child, equals: this.firstChild));

D.assert(this.firstChild == child);
this._firstChild = child.nextSibling;
}
else {
} else {
child._previousSibling._nextSibling = child.nextSibling;
}

}
else {
} else {
child._nextSibling._previousSibling = child.previousSibling;
}

this._lastChild = null;
}
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
return null;
public void addChildrenToScene(SceneBuilder builder, Offset childOffset) {
public void addChildrenToScene(SceneBuilder builder, Offset childOffset = null) {
child.addToScene(builder, childOffset);
if (childOffset == null || childOffset == Offset.zero) {
child._addToSceneWithRetainedRendering(builder);
} else {
child.addToScene(builder, childOffset);
}
child = child.nextSibling;
}
}

D.assert(transform != null);
}
public override List<DiagnosticsNode> debugDescribeChildren() {

public class OffsetLayer : ContainerLayer {
public OffsetLayer(Offset offset = null) {
this.offset = offset ?? Offset.zero;
this._offset = offset ?? Offset.zero;
}
Offset _offset;
public Offset offset {
get { return this._offset; }
set {
value = value ?? Offset.zero;
if (value != this._offset) {
this._offset = value;
this.markNeedsAddToScene();
}
}
}
public override void applyTransform(Layer child, Matrix3 transform) {
D.assert(child != null);
D.assert(transform != null);
transform.preTranslate((float) this.offset.dx, (float) this.offset.dy);
}
public Scene buildScene(SceneBuilder builder) {
this.updateSubtreeNeedsAddToScene();
this.addToScene(builder);
return builder.build();
public Offset offset;
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
this.addChildrenToScene(builder, this.offset + layerOffset);
var engineLayer = builder.pushOffset(
(float) (layerOffset.dx + this.offset.dx),
(float) (layerOffset.dy + this.offset.dy));
this.addChildrenToScene(builder);
builder.pop();
return engineLayer;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

Rect clipRect = null,
Clip clipBehavior = Clip.hardEdge
) {
D.assert(clipRect != null);
this.clipRect = clipRect;
this._clipRect = clipRect;
public readonly Rect clipRect;
Rect _clipRect;
public Rect clipRect {
get { return this._clipRect; }
set {
if (value != this._clipRect) {
this._clipRect = value;
this.markNeedsAddToScene();
}
}
}
Clip _clipBehavior;
this._clipBehavior = value;
if (value != this._clipBehavior) {
this._clipBehavior = value;
this.markNeedsAddToScene();
}
Clip _clipBehavior;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
bool enabled = true;
D.assert(() => {
enabled = !D.debugDisableClipLayers;

if (enabled) {
builder.pop();
}
return null;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

RRect clipRRect = null,
Clip clipBehavior = Clip.hardEdge
) {
D.assert(clipRRect != null);
this.clipRRect = clipRRect;
this._clipRRect = clipRRect;
public readonly RRect clipRRect;
RRect _clipRRect;
public RRect clipRRect {
get { return this._clipRRect; }
set {
if (value != this._clipRRect) {
this._clipRRect = value;
this.markNeedsAddToScene();
}
}
}
Clip _clipBehavior;
this._clipBehavior = value;
if (value != this._clipBehavior) {
this._clipBehavior = value;
this.markNeedsAddToScene();
}
Clip _clipBehavior;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
bool enabled = true;
D.assert(() => {
enabled = !D.debugDisableClipLayers;

if (enabled) {
builder.pop();
}
return null;
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {

}
public class ClipPathLayer : ContainerLayer {
public ClipPathLayer(
Path clipPath = null,
Clip clipBehavior = Clip.hardEdge
) {
D.assert(clipPath != null);
D.assert(clipBehavior != Clip.none);
this._clipPath = clipPath;
this._clipBehavior = clipBehavior;
}
Path _clipPath;
public Path clipPath {
get { return this._clipPath; }
set {
if (value != this._clipPath) {
this._clipPath = value;
this.markNeedsAddToScene();
}
}
}
Clip _clipBehavior;
public Clip clipBehavior {
get { return this._clipBehavior; }
set {
D.assert(value != Clip.none);
if (value != this._clipBehavior) {
this._clipBehavior = value;
this.markNeedsAddToScene();
}
}
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
bool enabled = true;
D.assert(() => {
enabled = !D.debugDisableClipLayers;
return true;
});
if (enabled) {
builder.pushClipPath(this.clipPath.shift(layerOffset));
}
this.addChildrenToScene(builder, layerOffset);
if (enabled) {
builder.pop();
}
return null;
}
}
public class TransformLayer : OffsetLayer {
public TransformLayer(Matrix3 transform = null, Offset offset = null) : base(offset) {
this._transform = transform ?? Matrix3.I();

Matrix3 _transform;
Matrix3 _lastEffectiveTransform;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
this._lastEffectiveTransform = this._transform;
var totalOffset = this.offset + layerOffset;

}
builder.pushTransform(this._lastEffectiveTransform);
this.addChildrenToScene(builder, Offset.zero);
this.addChildrenToScene(builder);
return null;
D.assert(transform != null);
transform.preConcat(this._lastEffectiveTransform);
}

}
public class OpacityLayer : ContainerLayer {
public OpacityLayer(int alpha = 255) {
this.alpha = alpha;
public OpacityLayer(int alpha = 255, Offset offset = null) {
this._alpha = alpha;
this._offset = offset ?? Offset.zero;
public int alpha;
int _alpha;
public int alpha {
get { return this._alpha; }
set {
if (value != this._alpha) {
this._alpha = value;
this.markNeedsAddToScene();
}
}
}
Offset _offset;
public Offset offset {
get { return this._offset; }
set {
value = value ?? Offset.zero;
if (value != this._offset) {
this._offset = value;
this.markNeedsAddToScene();
}
}
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
bool enabled = true;
D.assert(() => {
enabled = !D.debugDisableOpacityLayers;

builder.pushOpacity(this.alpha);
builder.pushOpacity(this.alpha, offset: this.offset + layerOffset);
}
this.addChildrenToScene(builder, layerOffset);

return null;
properties.add(new DiagnosticsProperty<Offset>("offset", this.offset));
}
}

}
public class LeaderLayer : ContainerLayer {
public readonly LayerLink link;
public Offset offset;
}
public readonly LayerLink link;
public Offset offset;
protected override bool alwaysNeedsAddToScene {
get { return true; }
}
public override void attach(object owner) {

internal Offset _lastOffset;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
D.assert(this.offset != null);
this._lastOffset = this.offset + layerOffset;
if (this._lastOffset != Offset.zero) {

if (this._lastOffset != Offset.zero) {
builder.pop();
}
return null;
}
public override void applyTransform(Layer child, Matrix3 transform) {

D.assert(link != null);
this.link = link;
this.showWhenUnlinked = showWhenUnlinked;
this.unlinkedOffset = unlinkedOffset;
this.linkedOffset = linkedOffset;
this.unlinkedOffset = unlinkedOffset ?? Offset.zero;
this.linkedOffset = linkedOffset ?? Offset.zero;
public readonly bool showWhenUnlinked;
public readonly Offset unlinkedOffset;
public readonly Offset linkedOffset;
public bool showWhenUnlinked;
public Offset unlinkedOffset;
public Offset linkedOffset;
Matrix3 _invertedTransform;
public Matrix3 getLastTransform() {
if (this._lastTransform == null) {

ancestor = layer;
layer = this;
List<ContainerLayer> inverseLayers = new List<ContainerLayer>();
List<ContainerLayer> inverseLayers = new List<ContainerLayer> {layer};
do {
layer = layer.parent;
inverseLayers.Add(layer);

Matrix3 inverseTransform = this._collectTransformForLayerChain(inverseLayers);
var inverse = Matrix3.I();
var invertible = inverseTransform.invert(inverseTransform);
var invertible = inverseTransform.invert(inverse);
if (!invertible) {
return;
}

this._lastTransform = inverseTransform;
}
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
protected override bool alwaysNeedsAddToScene {
get { return true; }
}
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
return;
return null;
this.addChildrenToScene(builder, Offset.zero);
this.addChildrenToScene(builder);
}
else {
} else {
this.addChildrenToScene(builder, Offset.zero);
this.addChildrenToScene(builder);
return null;
}
public override void applyTransform(Layer child, Matrix3 transform) {

transform.preConcat(this._lastTransform);
}
else {
} else {
transform.preConcat(Matrix3.makeTrans(this.unlinkedOffset.dx, this.unlinkedOffset.dy));
}
}

properties.add(new DiagnosticsProperty<LayerLink>("link", this.link));
properties.add(new TransformProperty("transform", this.getLastTransform(), defaultValue: null));
properties.add(new TransformProperty("transform", this.getLastTransform(),
defaultValue: Diagnostics.kNullDefaultValue));
}
}

8
Runtime/rendering/proxy_box.mixin.njk


return this.child.getMinIntrinsicWidth(height);
}
return 0.0;
return 0.0f;
}
protected override float computeMaxIntrinsicWidth(float height) {

return 0.0;
return 0.0f;
}
protected override float computeMinIntrinsicHeight(float width) {

return 0.0;
return 0.0f;
}
protected override float computeMaxIntrinsicHeight(float width) {

return 0.0;
return 0.0f;
}
protected override float? computeDistanceToActualBaseline(TextBaseline baseline) {

2
Runtime/rendering/view.cs


public void compositeFrame() {
var builder = new SceneBuilder();
this.layer.addToScene(builder, Offset.zero);
this.layer.buildScene(builder);
using (var scene = builder.build()) {
Window.instance.render(scene);
}

47
Runtime/ui/compositing.cs


using System;
using Unity.UIWidgets.flow;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.ui {
public class SceneBuilder {

this._currentLayer = layer;
}
public void pushTransform(Matrix3 matrix) {
public Layer pushTransform(Matrix3 matrix) {
return layer;
public void pushClipRect(Rect clipRect) {
public Layer pushOffset(float dx, float dy) {
var layer = new TransformLayer();
layer.transform = Matrix3.makeTrans(dx, dy);
this._pushLayer(layer);
return layer;
}
public Layer pushClipRect(Rect clipRect) {
return layer;
public void pushClipRRect(RRect clipRRect) {
public Layer pushClipRRect(RRect clipRRect) {
return layer;
}
public Layer pushClipPath(Path clipPath) {
var layer = new ClipPathLayer();
layer.clipPath = clipPath;
this._pushLayer(layer);
return layer;
public void pushOpacity(int alpha) {
public Layer pushOpacity(int alpha, Offset offset = null) {
offset = offset ?? Offset.zero;
layer.offset = offset;
return layer;
}
public void addRetained(Layer layer) {
if (this._currentLayer == null) {
return;
}
this._currentLayer.add(layer);
}
public void pop() {

}
public void addPicture(Offset offset, Picture picture,
bool isComplex = false, bool willChange = false) {
bool isComplexHint = false, bool willChangeHint = false) {
D.assert(offset != null);
D.assert(picture != null);
if (this._currentLayer == null) {
return;
}

layer.picture = picture;
layer.isComplex = isComplex;
layer.willChange = willChange;
layer.isComplex = isComplexHint;
layer.willChange = willChangeHint;
this._currentLayer.add(layer);
}
}

8
Runtime/ui/geometry.cs


}
public Rect expandToInclude(Rect other) {
if (this.isEmpty) {
return other;
}
if (other == null || other.isEmpty) {
return this;
}
return fromLTRB(
Mathf.Min(this.left, other.left),
Mathf.Min(this.top, other.top),

10
Runtime/ui/painting/canvas.cs


this._recorder = recorder;
}
readonly PictureRecorder _recorder;
protected readonly PictureRecorder _recorder;
int _saveCount = 1;

}
public Matrix3 getTotalMatrix() {
throw new Exception("not available in recorder");
return this._recorder.getTotalMatrix();
}
public void resetMatrix() {

});
}
public float getDevicePixelRatio() {
public virtual float getDevicePixelRatio() {
throw new Exception("not available in recorder");
}

});
}
public void flush() {
public virtual void flush() {
throw new Exception("not available in recorder");
this._recorder.reset();
}
}
}

21
Runtime/ui/painting/canvas_clip.cs


using System.Collections.Generic;
using System.Linq;
using Unity.UIWidgets.foundation;
using UnityEngine;

public const uint wideOpenGenID = 2;
public readonly List<ClipElement> stack = new List<ClipElement>();
ClipElement _lastElement;
Rect _bound;
int _saveCount;

}
void _restoreTo(int saveCount) {
while (this.stack.Count > 0) {
var element = this.stack[this.stack.Count - 1];
if (element.saveCount <= saveCount) {
while (this._lastElement != null) {
if (this._lastElement.saveCount <= saveCount) {
this._lastElement = this.stack.Count == 0 ? null : this.stack[this.stack.Count - 1];
}
}

}
void _pushElement(ClipElement element) {
ClipElement prior = this.stack.LastOrDefault();
ClipElement prior = this._lastElement;
if (prior != null) {
if (prior.isEmpty()) {
return;

}
this.stack.Add(element);
this._lastElement = element;
if (this.stack.Count == 0) {
if (this._lastElement == null) {
var element = this.stack.Last();
var element = this._lastElement;
bound = element.getBound();
isIntersectionOfRects = element.isIntersectionOfRects();
}

public readonly Rect scissor;
public readonly List<ClipElement> maskElements = new List<ClipElement>();
ClipElement _lastElement;
public bool isEmpty() {
return this.scissor != null && this.scissor.isEmpty;

var element = this.maskElements.LastOrDefault();
var element = this._lastElement;
if (element == null) {
return ClipStack.wideOpenGenID;
}

}
stackBounds = layerBounds.intersect(stackBounds);
if (iior) {
this.scissor = stackBounds;
return;

}
this.maskElements.Add(element);
this._lastElement = element;
}
}
}

562
Runtime/ui/painting/canvas_impl.cs


using System;
using System.Collections.Generic;
using System.Linq;
public class CommandBufferCanvas : Canvas {
public class PictureFlusher {
int _saveCount;
public CommandBufferCanvas(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool) {
RenderLayer _currentLayer;
public PictureFlusher(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool) {
D.assert(devicePixelRatio > 0);
D.assert(meshPool != null);
this.reset();
RenderLayer _getLayer() {
D.assert(this._layers.Count > 0);
return this._layers.Last();
public float getDevicePixelRatio() {
return this._devicePixelRatio;
void _reset() {
foreach (var layer in this._layers) {
this._clearLayer(layer);
}
RenderLayer firstLayer;
if (this._layers.Count == 0) {
var width = this._renderTexture.width;
var height = this._renderTexture.height;
State _getState() {
var layer = this._getLayer();
D.assert(layer.states.Count > 0);
return layer.states.Last();
}
var bounds = Rect.fromLTWH(0, 0,
width * this._fringeWidth,
height * this._fringeWidth);
firstLayer = new RenderLayer {
width = width,
height = height,
layerBounds = bounds,
};
} else {
D.assert(this._layers.Count > 0);
firstLayer = this._layers[0];
firstLayer = new RenderLayer {
width = firstLayer.width,
height = firstLayer.height,
layerBounds = firstLayer.layerBounds,
};
}
public int getSaveCount() {
return this._saveCount;
this._layers.Clear();
this._layers.Add(firstLayer);
this._currentLayer = firstLayer;
public void save() {
this._saveCount++;
var layer = this._getLayer();
layer.states.Add(this._getState().copy());
void _save() {
var layer = this._currentLayer;
layer.currentState = layer.currentState.copy();
layer.states.Add(layer.currentState);
public void saveLayer(Rect bounds, Paint paint) {
void _saveLayer(Rect bounds, Paint paint) {
this._saveCount++;
var state = this._getState();
var parentLayer = this._currentLayer;
var state = parentLayer.currentState;
textureWidth = Mathf.Max(textureWidth, 1);
if (textureWidth < 1) {
textureWidth = 1;
}
textureHeight = Mathf.Max(textureHeight, 1);
if (textureHeight < 1) {
textureHeight = 1;
}
var parentLayer = this._getLayer();
var layer = new RenderLayer {
rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),
width = textureWidth,

parentLayer.layers.Add(layer);
this._layers.Add(layer);
this._currentLayer = layer;
public void restore() {
this._saveCount--;
var layer = this._getLayer();
void _restore() {
var layer = this._currentLayer;
layer.currentState = layer.states[layer.states.Count - 1];
var state = this._getState();
var currentLayer = this._currentLayer = this._layers[this._layers.Count - 1];
var state = currentLayer.currentState;
var mesh = ImageMeshGenerator.imageMesh(state.matrix, Rect.one, layer.layerBounds);

var renderDraw = CanvasShader.texRT(this._getLayer(), layer.layerPaint, mesh, layer);
this._getLayer().draws.Add(renderDraw);
var renderDraw = CanvasShader.texRT(currentLayer, layer.layerPaint, mesh, layer);
currentLayer.draws.Add(renderDraw);
public void translate(float dx, float dy) {
var state = this._getState();
void _translate(float dx, float dy) {
var state = this._currentLayer.currentState;
public void scale(float sx, float? sy = null) {
var state = this._getState();
void _scale(float sx, float? sy = null) {
var state = this._currentLayer.currentState;
public void rotate(float radians, Offset offset = null) {
var state = this._getState();
void _rotate(float radians, Offset offset = null) {
var state = this._currentLayer.currentState;
}
else {
} else {
var matrix = Matrix3.makeRotate(radians, offset.dx, offset.dy);
matrix.postConcat(state.matrix);
state.matrix = matrix;

public void skew(float sx, float sy) {
var state = this._getState();
var matrix = Matrix3.makeSkew(sx, sy);
void _skew(float sx, float sy) {
var state = this._currentLayer.currentState;
var matrix = Matrix3.makeSkew( sx, sy);
public void concat(Matrix3 matrix) {
var state = this._getState();
void _concat(Matrix3 matrix) {
var state = this._currentLayer.currentState;
public Matrix3 getTotalMatrix() {
var state = this._getState();
return state.matrix;
}
public void resetMatrix() {
var state = this._getState();
void _resetMatrix() {
var state = this._currentLayer.currentState;
public void setMatrix(Matrix3 matrix) {
var state = this._getState();
void _setMatrix(Matrix3 matrix) {
var state = this._currentLayer.currentState;
public float getDevicePixelRatio() {
return this._devicePixelRatio;
}
public void clipRect(Rect rect) {
void _clipRect(Rect rect) {
this.clipPath(path);
this._clipPath(path);
public void clipRRect(RRect rrect) {
void _clipRRect(RRect rrect) {
this.clipPath(path);
this._clipPath(path);
public void clipPath(Path path) {
var layer = this._getLayer();
var state = this._getState();
void _clipPath(Path path) {
var layer = this._currentLayer;
var state = layer.currentState;
public void drawLine(Offset from, Offset to, Paint paint) {
var path = new Path();
path.moveTo(from.dx, from.dy);
path.lineTo(to.dx, to.dy);
this.drawPath(path, paint);
}
public void drawRect(Rect rect, Paint paint) {
var path = new Path();
path.addRect(rect);
this.drawPath(path, paint);
}
public void drawRRect(RRect rrect, Paint paint) {
var path = new Path();
path.addRRect(rrect);
this.drawPath(path, paint);
}
public void drawDRRect(RRect outer, RRect inner, Paint paint) {
var path = new Path();
path.addRRect(outer);
path.addRRect(inner);
path.winding(PathWinding.clockwise);
this.drawPath(path, paint);
}
public void drawOval(Rect rect, Paint paint) {
var w = rect.width / 2;
var h = rect.height / 2;
var path = new Path();
path.addEllipse(rect.left + w, rect.top + h, w, h);
this.drawPath(path, paint);
}
public void drawCircle(Offset c, float radius, Paint paint) {
var path = new Path();
path.addCircle(c.dx, c.dy, radius);
this.drawPath(path, paint);
}
public void drawArc(Rect rect, float startAngle, float sweepAngle, bool useCenter, Paint paint) {
//var path = new Path();
}
void _tryAddScissor(RenderLayer layer, Rect scissor) {
if (scissor == layer.lastScissor) {
return;

});
layer.lastScissor = scissor;
}
var layer = this._getLayer();
var layer = this._currentLayer;
var layerBounds = layer.layerBounds;
ReducedClip reducedClip = new ReducedClip(layer.clipStack, layerBounds, queryBounds);
if (reducedClip.isEmpty()) {

if (scissor == layerBounds) {
this._tryAddScissor(layer, null);
}
else {
} else {
deviceScissor = deviceScissor.roundIn();
deviceScissor = deviceScissor.roundOut();
this._tryAddScissor(layer, deviceScissor);
}

layer.ignoreClip = true;
}
else {
} else {
layer.ignoreClip = false;
var boundsMesh = new MeshMesh(reducedClip.scissor);

return true;
}
void _setLastClipGenId(uint clipGenId, Rect clipBounds) {
var layer = this._currentLayer;
layer.lastClipGenId = clipGenId;
layer.lastClipBounds = clipBounds;
}
RenderLayer _createMaskLayer(RenderLayer parentLayer, Rect maskBounds, Action<Paint> drawCallback,
Paint paint) {
bool _mustRenderClip(uint clipGenId, Rect clipBounds) {
var layer = this._currentLayer;
return layer.lastClipGenId != clipGenId || layer.lastClipBounds != clipBounds;
}
RenderLayer _createMaskLayer(RenderLayer parentLayer, Rect maskBounds, Action<Paint> drawCallback, Paint paint) {
textureWidth = Mathf.Max(1, textureWidth);
if (textureWidth < 1) {
textureWidth = 1;
}
textureHeight = Mathf.Max(1, textureHeight);
if (textureHeight < 1) {
textureHeight = 1;
}
var maskLayer = new RenderLayer {
rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),

parentLayer.layers.Add(maskLayer);
this._layers.Add(maskLayer);
this._currentLayer = maskLayer;
var parentState = parentLayer.states.Last();
var maskState = maskLayer.states.Last();
var parentState = parentLayer.states[parentLayer.states.Count - 1];
var maskState = maskLayer.states[maskLayer.states.Count - 1];
maskState.matrix = parentState.matrix;
drawCallback(Paint.shapeOnly(paint));

this._currentLayer = this._layers[this._layers.Count - 1];
return maskLayer;
}

var textureWidth = Mathf.CeilToInt(maskLayer.width / scaleFactor);
textureWidth = Mathf.Max(1, textureWidth);
var textureHeight = Mathf.CeilToInt(maskLayer.height / scaleFactor);
textureHeight = Mathf.Max(1, textureHeight);
var textureWidth = Mathf.CeilToInt((float) maskLayer.width / scaleFactor);
if (textureWidth < 1) {
textureWidth = 1;
}
var textureHeight = Mathf.CeilToInt((float) maskLayer.height / scaleFactor);
if (textureHeight < 1) {
textureHeight = 1;
}
var blurXLayer = new RenderLayer {
rtID = Shader.PropertyToID("_rtID_" + this._layers.Count + "_" + parentLayer.layers.Count),

}
void _drawWithMaskFilter(Rect meshBounds, Action<Paint> drawAction, Paint paint, MaskFilter maskFilter) {
var layer = this._getLayer();
var layer = this._currentLayer;
var clipBounds = layer.layerBounds;
Rect stackBounds;

return;
}
var state = this._getState();
var state = layer.currentState;
float sigma = state.scale * maskFilter.sigma;
if (sigma <= 0) {
return;

layer.draws.Add(CanvasShader.texRT(layer, paint, blurMesh, blurLayer));
}
public void drawPath(Path path, Paint paint) {
void _drawPath(Path path, Paint paint) {
var state = this._getState();
var state = this._currentLayer.currentState;
Action<Paint> drawMesh = (Paint p) => {
Action<Paint> drawMesh = p => {
var layer = this._getLayer();
var layer = this._currentLayer;
if (convex) {
layer.draws.Add(CanvasShader.convexFill(layer, p, mesh));
}

this._drawWithMaskFilter(mesh.bounds, drawMesh, paint, paint.maskFilter);
return;
}
var state = this._getState();
var state = this._currentLayer.currentState;
float strokeWidth = (paint.strokeWidth * state.scale).clamp(0, 200.0f);
float alpha = 1.0f;

paint.strokeJoin,
paint.strokeMiterLimit).transform(state.matrix);
Action<Paint> drawMesh = (Paint p) => {
Action<Paint> drawMesh = p => {
var layer = this._getLayer();
var layer = this._currentLayer;
public void drawImage(Image image, Offset offset, Paint paint) {
void _drawImage(Image image, Offset offset, Paint paint) {
this.drawImageRect(image,
this._drawImageRect(image,
null,
Rect.fromLTWH(
offset.dx, offset.dy,

}
public void drawImageRect(Image image, Rect dst, Paint paint) {
this.drawImageRect(image, null, dst, paint);
}
public void drawImageRect(Image image, Rect src, Rect dst, Paint paint) {
void _drawImageRect(Image image, Rect src, Rect dst, Paint paint) {
D.assert(image != null);
D.assert(dst != null);
D.assert(paint != null);

}
else {
} else {
var state = this._getState();
var layer = this._currentLayer;
var state = layer.currentState;
var layer = this._getLayer();
public void drawImageNine(Image image, Rect center, Rect dst, Paint paint) {
this.drawImageNine(image, null, center, dst, paint);
}
public void drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) {
void _drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) {
D.assert(image != null);
D.assert(center != null);
D.assert(dst != null);

var scaleY = 1f / image.height;
if (src == null) {
src = Rect.one;
}
else {
src = src.scale(scaleX, scaleY);
} else {
src = src.scale(scaleX, scaleY);
var state = this._getState();
var layer = this._currentLayer;
var state = layer.currentState;
var mesh = ImageMeshGenerator.imageNineMesh(state.matrix, src, center, image.width, image.height, dst);
var mesh = ImageMeshGenerator.imageNineMesh(state.matrix, src, center, image.width, image.height, dst);
var layer = this._getLayer();
public void drawPicture(Picture picture) {
this.save();
void _drawPicture(Picture picture, bool needsSave = true) {
if (needsSave) {
this._save();
}
int saveCount = 0;

case DrawSave _:
saveCount++;
this.save();
this._save();
this.saveLayer(cmd.rect, cmd.paint);
this._saveLayer(cmd.rect, cmd.paint);
break;
}
case DrawRestore _: {

}
this.restore();
this._restore();
this.translate(cmd.dx, cmd.dy);
this._translate(cmd.dx, cmd.dy);
this.scale(cmd.sx, cmd.sy);
this._scale(cmd.sx, cmd.sy);
this.rotate(cmd.radians, cmd.offset);
this._rotate(cmd.radians, cmd.offset);
this.skew(cmd.sx, cmd.sy);
this._skew(cmd.sx, cmd.sy);
this.concat(cmd.matrix);
this._concat(cmd.matrix);
this.resetMatrix();
this._resetMatrix();
this.setMatrix(cmd.matrix);
this._setMatrix(cmd.matrix);
this.clipRect(cmd.rect);
this._clipRect(cmd.rect);
this.clipRRect(cmd.rrect);
this._clipRRect(cmd.rrect);
this.clipPath(cmd.path);
this._clipPath(cmd.path);
this.drawPath(cmd.path, cmd.paint);
this._drawPath(cmd.path, cmd.paint);
this.drawImage(cmd.image, cmd.offset, cmd.paint);
this._drawImage(cmd.image, cmd.offset, cmd.paint);
this.drawImageRect(cmd.image, cmd.src, cmd.dst, cmd.paint);
this._drawImageRect(cmd.image, cmd.src, cmd.dst, cmd.paint);
this.drawImageNine(cmd.image, cmd.src, cmd.center, cmd.dst, cmd.paint);
this._drawImageNine(cmd.image, cmd.src, cmd.center, cmd.dst, cmd.paint);
this.drawPicture(cmd.picture);
this._drawPicture(cmd.picture);
this.drawTextBlob(cmd.textBlob, cmd.offset, cmd.paint);
this._drawTextBlob(cmd.textBlob, cmd.offset, cmd.paint);
break;
}
default:

throw new Exception("unmatched save/restore in picture");
}
this.restore();
if (needsSave) {
this._restore();
}
public void drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) {
void _drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) {
var state = this._getState();
var state = this._currentLayer.currentState;
matrix.preTranslate(offset.dx, offset.dy);
matrix.preTranslate(offset.dx, offset.dy);
var font = FontManager.instance.getOrCreate(textBlob.style.fontFamily).font;
var tex = font.material.mainTexture;

}
var layer = this._getLayer();
var layer = this._currentLayer;
layer.draws.Add(CanvasShader.texAlpha(layer, p, mesh, tex));
};

drawMesh(paint);
}
public void flush() {
if (this._saveCount > 0) {
throw new Exception("unmatched save/restore");
}
public void flush(Picture picture) {
this._reset();
this._drawPicture(picture, false);
var layer = this._getLayer();
var layer = this._currentLayer;
if (layer.draws.Count == 0) {
D.assert(layer.layers.Count == 0);
return;

this._clearLayer(layer);
}
public void reset() {
foreach (var layer in this._layers) {
this._clearLayer(layer);
}
this._saveCount = 0;
RenderLayer firstLayer;
if (this._layers.Count == 0) {
var bounds = Rect.fromLTWH(0, 0,
this._renderTexture.width / this._devicePixelRatio,
this._renderTexture.height / this._devicePixelRatio);
firstLayer = new RenderLayer {
width = this._renderTexture.width,
height = this._renderTexture.height,
layerBounds = bounds,
};
}
else {
D.assert(this._layers.Count > 0);
firstLayer = this._layers[0];
firstLayer = new RenderLayer {
width = firstLayer.width,
height = firstLayer.height,
layerBounds = firstLayer.layerBounds,
};
}
this._layers.Clear();
this._layers.Add(firstLayer);
}
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) {
void _drawLayer(RenderLayer layer, CommandBuffer cmdBuf) {
foreach (var subLayer in layer.layers) {
var desc = new RenderTextureDescriptor(
subLayer.width, subLayer.height,

};
cmdBuf.GetTemporaryRT(subLayer.rtID, desc, FilterMode.Bilinear);
this._drawLayer(subLayer, cmdBuf);
}

if (cmd.mesh.matrix == null) {
cmd.properties.SetFloatArray(RenderDraw.matId, RenderDraw.idMat3.fMat);
}
else {
} else {
cmd.properties.SetFloatArray(RenderDraw.matId, cmd.mesh.matrix.fMat);
}

}
}
else {
} else {
break;
}
}

}
void _clearLayer(RenderLayer layer) {
for (var index = 0; index < layer.draws.Count; index++) {
var cmdObj = layer.draws[index];
foreach (var cmdObj in layer.draws) {
switch (cmdObj) {
case RenderDraw cmd:
if (cmd.meshObjCreated) {

}
break;
}
}

layer.layers.Clear();
}
void _setLastClipGenId(uint clipGenId, Rect clipBounds) {
var layer = this._getLayer();
layer.lastClipGenId = clipGenId;
layer.lastClipBounds = clipBounds;
}
bool _mustRenderClip(uint clipGenId, Rect clipBounds) {
var layer = this._getLayer();
internal class RenderLayer {
public int rtID;
public int width;
public int height;
public Rect layerBounds;
public Paint layerPaint;
public readonly List<object> draws = new List<object>();
public readonly List<RenderLayer> layers = new List<RenderLayer>();
public readonly List<State> states = new List<State>();
public State currentState;
public readonly ClipStack clipStack = new ClipStack();
public uint lastClipGenId;
public Rect lastClipBounds;
public Rect lastScissor;
public bool ignoreClip;
return layer.lastClipGenId != clipGenId || layer.lastClipBounds != clipBounds;
Vector4? _viewport;
public Vector4 viewport {
get {
if (!this._viewport.HasValue) {
this._viewport = new Vector4(
this.layerBounds.left,
this.layerBounds.top,
this.layerBounds.width,
this.layerBounds.height);
}
return this._viewport.Value;
}
}
public RenderLayer() {
this.currentState = new State();
this.states.Add(this.currentState);
}
Matrix3 _matrix;
float? _scale;

}
public Matrix3 matrix {
get { return this._matrix; }
set {

if (this._scale == null) {
this._scale = XformUtils.getScale(this._matrix);
}
return this._scale.Value;
}
}

}
}
internal class RenderLayer {
public int rtID;
public int width;
public int height;
public Rect layerBounds;
public Paint layerPaint;
public readonly List<object> draws = new List<object>();
public readonly List<RenderLayer> layers = new List<RenderLayer>();
public readonly List<State> states = new List<State> {new State()};
public readonly ClipStack clipStack = new ClipStack();
public uint lastClipGenId;
public Rect lastClipBounds;
public Rect lastScissor;
public bool ignoreClip;
Vector4? _viewport;
public Vector4 viewport {
get {
if (!this._viewport.HasValue) {
this._viewport = new Vector4(
this.layerBounds.left,
this.layerBounds.top,
this.layerBounds.width,
this.layerBounds.height);
}
return this._viewport.Value;
}
}
}
internal class RenderDraw {
public MeshMesh mesh;
public int pass;

}
}
public class CommandBufferCanvas : RecorderCanvas {
readonly PictureFlusher _flusher;
public CommandBufferCanvas(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool)
: base(new PictureRecorder()) {
this._flusher = new PictureFlusher(renderTexture, devicePixelRatio, meshPool);
}
public override float getDevicePixelRatio() {
return this._flusher.getDevicePixelRatio();
}
public override void flush() {
var picture = this._recorder.endRecording();
this._recorder.reset();
this._flusher.flush(picture);
}
}
static class XformUtils {
public static float getAverageScale(Matrix3 matrix) {
return (getScaleX(matrix) + getScaleY(matrix)) * 0.5f;

if (matrix.getSkewY() == 0) {
return matrix.getScaleX();
}
return Mathf.Sqrt(x * x + y * y);
}

// geometric mean of len0 and len1.
return Mathf.Sqrt(scaleX * scaleY);
}
public static float mapRadius(Matrix3 matrix, float radius) {
return getScale(matrix) * radius;
}

return new MeshMesh(matrix, vertices, _imageTriangles, uv);
}
public static MeshMesh imageNineMesh(Matrix3 matrix, Rect src, Rect center, int srcWidth, int srcHeight,
Rect dst) {
public static MeshMesh imageNineMesh(Matrix3 matrix, Rect src, Rect center, int srcWidth, int srcHeight, Rect dst) {
float x0 = dst.left;
float x3 = dst.right;
float x1 = x0 + ((center.left - src.left) * srcWidth);

uv.Add(new Vector2(tx2, ty3));
vertices.Add(new Vector2(x3, y3));
uv.Add(new Vector2(tx3, ty3));
}
}
}
}

54
Runtime/ui/painting/canvas_shader.cs


}
}
public static CommandBufferCanvas.RenderDraw convexFill(CommandBufferCanvas.RenderLayer layer, Paint paint,
public static PictureFlusher.RenderDraw convexFill(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw fill0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.RenderDraw fill0(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
var mat = _fill0Mat.getMaterial(layer.ignoreClip);

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw fill1(CommandBufferCanvas.RenderLayer layer, Paint paint,
public static PictureFlusher.RenderDraw fill1(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh.boundsMesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw stroke0(CommandBufferCanvas.RenderLayer layer, Paint paint,
public static PictureFlusher.RenderDraw stroke0(PictureFlusher.RenderLayer layer, Paint paint,
float alpha, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw stroke1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.RenderDraw stroke1(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
var mat = _stroke1Mat;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw stencilClear(
CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.RenderDraw stencilClear(
PictureFlusher.RenderLayer layer, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
var mat = _stencilMat;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw stencil0(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.RenderDraw stencil0(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
var mat = _stencilMat;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw stencil1(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.RenderDraw stencil1(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
Vector4 viewport = layer.viewport;
var mat = _stencilMat;

return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw tex(CommandBufferCanvas.RenderLayer layer, Paint paint,
public static PictureFlusher.RenderDraw tex(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, Image image) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

props.SetTexture("_tex", image.texture);
props.SetInt("_texMode", image.texture is RenderTexture ? 1 : 0); // pre alpha if RT else post alpha
return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

}
public static CommandBufferCanvas.RenderDraw texRT(CommandBufferCanvas.RenderLayer layer, Paint paint,
MeshMesh mesh, CommandBufferCanvas.RenderLayer renderLayer) {
public static PictureFlusher.RenderDraw texRT(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, PictureFlusher.RenderLayer renderLayer) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

props.SetInt("_texMode", 1); // pre alpha
return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

}
public static CommandBufferCanvas.RenderDraw texAlpha(CommandBufferCanvas.RenderLayer layer, Paint paint,
public static PictureFlusher.RenderDraw texAlpha(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, Texture tex) {
Vector4 viewport = layer.viewport;
Matrix3 ctm = layer.states[layer.states.Count - 1].matrix;

props.SetTexture("_tex", tex);
props.SetInt("_texMode", 2); // alpha only
return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

public static CommandBufferCanvas.RenderDraw maskFilter(CommandBufferCanvas.RenderLayer layer, MeshMesh mesh,
CommandBufferCanvas.RenderLayer renderLayer, float radius, Vector2 imgInc, float[] kernel) {
public static PictureFlusher.RenderDraw maskFilter(PictureFlusher.RenderLayer layer, MeshMesh mesh,
PictureFlusher.RenderLayer renderLayer, float radius, Vector2 imgInc, float[] kernel) {
Vector4 viewport = layer.viewport;
var mat = _filterMat;

props.SetVector("_mf_imgInc", imgInc);
props.SetFloatArray("_mf_kernel", kernel);
return new CommandBufferCanvas.RenderDraw {
return new PictureFlusher.RenderDraw {
mesh = mesh,
pass = pass,
material = mat,

47
Runtime/ui/painting/path.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Unity.UIWidgets.foundation;
using UnityEngine;

public Path() {
this._reset();
}
public override string ToString() {
var sb = new StringBuilder("Path: count = " + this._commands.Count);
var i = 0;
while (i < this._commands.Count) {
var cmd = (PathCommand) this._commands[i];
switch (cmd) {
case PathCommand.moveTo:
sb.Append(", moveTo(" + this._commands[i + 1] + ", " + this._commands[i + 2] + ")");
i += 3;
break;
case PathCommand.lineTo:
sb.Append(", lineTo(" + this._commands[i + 1] + ", " + this._commands[i + 2] + ")");
i += 3;
break;
case PathCommand.bezierTo:
sb.Append(", bezierTo(" + this._commands[i + 1] + ", " + this._commands[i + 2] +
", " + this._commands[i + 3] + ", " + this._commands[i + 4] +
", " + this._commands[i + 5] + ", " + this._commands[i + 6] + ")");
i += 7;
break;
case PathCommand.close:
sb.Append(", close()");
i++;
break;
case PathCommand.winding:
sb.Append(", winding(" + (PathWinding) this._commands[i + 1] + ")");
i += 2;
break;
default:
D.assert(false, "unknown cmd: " + cmd);
break;
}
}
return sb.ToString();
}
void _reset() {

this._appendCommands(commands.ToArray());
}
public Path shift(Offset offset) {
offset = offset ?? Offset.zero;
var path = new Path();
path.addPath(this, offset);
return path;
}
D.assert(offset != null);
var commands = new List<float>();

74
Runtime/ui/painting/picture.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public class Picture {

readonly List<CanvasState> _states = new List<CanvasState>();
public PictureRecorder() {
this.reset();
}
CanvasState _getState() {
D.assert(this._states.Count > 0);
return this._states[this._states.Count - 1];
}
public Matrix3 getTotalMatrix() {
return this._getState().xform;
}
public void reset() {
this._drawCmds.Clear();
this._states.Clear();
this._states.Add(new CanvasState {
xform = Matrix3.I(),
scissor = null,

});
}
CanvasState _getState() {
D.assert(this._states.Count > 0);
return this._states.Last();
}
var state = this._getState();
return new Picture(this._drawCmds, state.paintBounds);
var state = this._getState();
return new Picture(new List<DrawCmd>(this._drawCmds), state.paintBounds);
}
public void addDrawCmd(DrawCmd drawCmd) {

if (!stateToRestore.saveLayer) {
state.paintBounds = stateToRestore.paintBounds;
}
else {
} else {
state.xform = new Matrix3(state.xform);
state.xform = new Matrix3(state.xform);
state.xform = new Matrix3(state.xform);
}
else {
} else {
state.xform = new Matrix3(state.xform);
state.xform = new Matrix3(state.xform);
state.xform.reset();
state.xform = Matrix3.I();
break;
}
case DrawSetMatrix cmd: {

if (paint.style == PaintingStyle.fill) {
var cache = path.flatten(scale * devicePixelRatio);
mesh = cache.getFillMesh(out _).transform(state.xform);
}
else {
} else {
float strokeWidth = (paint.strokeWidth * scale).clamp(0, 200.0f);
float fringeWidth = 1 / devicePixelRatio;

paint.strokeJoin,
paint.strokeMiterLimit).transform(state.xform);
}
this._addPaintBounds(mesh.bounds);
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
float sigma = scale * paint.maskFilter.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(mesh.bounds.inflate(sigma3));
} else {
this._addPaintBounds(mesh.bounds);
}
break;
}
case DrawImage cmd: {

}
case DrawTextBlob cmd: {
var state = this._getState();
var scale = XformUtils.getScale(state.xform);
this._addPaintBounds(rect);
var paint = cmd.paint;
if (paint.maskFilter != null && paint.maskFilter.sigma != 0) {
float sigma = scale * paint.maskFilter.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(rect.inflate(sigma3));
} else {
this._addPaintBounds(rect);
}
break;
}
default:

paintBounds = paintBounds.intersect(state.scissor);
}
if (paintBounds == null || paintBounds.isEmpty) {
return;
}
}
else {
} else {
state.paintBounds = state.paintBounds.expandToInclude(paintBounds);
}
}

2
Runtime/ui/txt/layout.cs


var rect = Rect.fromLTRB(characterInfo.minX, -characterInfo.maxY, characterInfo.maxX,
-characterInfo.minY);
rect = rect.translate(this._advance, 0);
if (this._bounds == null) {
if (this._bounds == null || this._bounds.isEmpty) {
this._bounds = rect;
}
else {

34
Runtime/ui/txt/linebreaker.cs


void _addWordBreak(int offset, float preBreak, float postBreak, int preSpaceCount, int postSpaceCount,
float penalty) {
Candidate cand = new Candidate();
float width = this._candidates[this._candidates.Count - 1].preBreak;
if (postBreak - width > this._lineWidth) {
int i = this._candidates[this._candidates.Count - 1].offset;

if (w > 0) {
cand.offset = i;
cand.preBreak = width;
cand.postBreak = width;
cand.preSpaceCount = postSpaceCount;
cand.preSpaceCount = postSpaceCount;
cand.penalty = ScoreDesperate;
this._addCandidate(cand);
this._addCandidate(new Candidate {
offset = i,
preBreak = width,
postBreak = width,
preSpaceCount = postSpaceCount,
postSpaceCount = postSpaceCount,
penalty = ScoreDesperate,
});
cand.offset = offset;
cand.preBreak = preBreak;
cand.postBreak = postBreak;
cand.penalty = penalty;
cand.preSpaceCount = preSpaceCount;
cand.preSpaceCount = postSpaceCount;
this._addCandidate(cand);
this._addCandidate(new Candidate {
offset = offset,
preBreak = preBreak,
postBreak = postBreak,
preSpaceCount = preSpaceCount,
postSpaceCount = postSpaceCount,
penalty = penalty
});
}

7
Runtime/widgets/widget_inspector.cs


// public float _textPainterMaxWidth;
public override void addToScene(SceneBuilder builder, Offset layerOffset) {
internal override flow.Layer addToScene(SceneBuilder builder, Offset layerOffset = null) {
layerOffset = layerOffset ?? Offset.zero;
return;
return null;
}
RenderObject selected = this.selection.current;

}
builder.addPicture(layerOffset, this._picture);
return null;
}

46
Runtime/flow/clip_path_layer.cs


using Unity.UIWidgets.foundation;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.flow {
public class ClipPathLayer : ContainerLayer {
Path _clipPath;
public Path clipPath {
set { this._clipPath = value; }
}
public override void preroll(PrerollContext context, Matrix3 matrix) {
var previousCullRect = context.cullRect;
var clipPathBounds = this._clipPath.getBounds();
context.cullRect = context.cullRect.intersect(clipPathBounds);
if (!context.cullRect.isEmpty) {
var childPaintBounds = Rect.zero;
this.prerollChildren(context, matrix, ref childPaintBounds);
childPaintBounds = childPaintBounds.intersect(clipPathBounds);
if (!childPaintBounds.isEmpty) {
this.paintBounds = childPaintBounds;
}
}
context.cullRect = previousCullRect;
}
public override void paint(PaintContext context) {
D.assert(this.needsPainting);
var canvas = context.canvas;
canvas.save();
canvas.clipPath(this._clipPath);
try {
this.paintChildren(context);
} finally {
canvas.restore();
}
}
}
}

11
Runtime/flow/clip_path_layer.cs.meta


fileFormatVersion: 2
guid: c5d70cbaf99774a12941c3b6cb24efc5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存