浏览代码

Merge branch 'master' into layout

/main
Yuncong Zhang 5 年前
当前提交
eaec41e9
共有 146 个文件被更改,包括 7487 次插入367 次删除
  1. 1
      Runtime/editor/rasterizer.cs
  2. 3
      Runtime/rendering/view.cs
  3. 16
      Runtime/ui/matrix.cs
  4. 28
      Runtime/ui/painting/path.cs
  5. 54
      Runtime/ui/painting/shader.cs
  6. 101
      Runtime/ui/painting/shadow_utils.cs
  7. 159
      Runtime/ui/painting/txt/mesh_generator.cs
  8. 2
      Runtime/ui/painting/txt/text_blob.cs
  9. 2
      Runtime/widgets/binding.cs
  10. 2
      Samples/UIWidgetSample/NavigationSample.cs
  11. 9
      Samples/UIWidgetSample/TextInput.unity
  12. 240
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs
  13. 174
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs
  14. 2
      Runtime/ui/renderer/compositeCanvas/compositing.cs
  15. 3
      Runtime/ui/renderer/compositeCanvas/flow/clip_path_layer.cs
  16. 7
      Runtime/ui/renderer/compositeCanvas/flow/clip_rect_layer.cs
  17. 5
      Runtime/ui/renderer/compositeCanvas/flow/clip_rrect_layer.cs
  18. 5
      Runtime/ui/renderer/compositeCanvas/flow/container_layer.cs
  19. 8
      Runtime/ui/renderer/compositeCanvas/flow/transform_layer.cs
  20. 5
      Runtime/ui/renderer/compositeCanvas/flow/texture_layer.cs
  21. 5
      Runtime/ui/renderer/compositeCanvas/flow/backdrop_filter_layer.cs
  22. 21
      Runtime/ui/renderer/compositeCanvas/flow/opacity_layer.cs
  23. 15
      Runtime/ui/renderer/compositeCanvas/flow/picture_layer.cs
  24. 2
      Runtime/ui/renderer/compositeCanvas/flow/layer_tree.cs
  25. 46
      Runtime/ui/renderer/compositeCanvas/flow/physical_shape_layer.cs
  26. 1
      Runtime/ui/renderer/compositeCanvas/flow/raster_cache.cs
  27. 3
      Runtime/ui/renderer/compositeCanvas/flow/instrumentation.cs
  28. 65
      Runtime/ui/painting/utils.cs
  29. 11
      Runtime/ui/painting/utils.cs.meta
  30. 8
      Runtime/ui/renderer.meta
  31. 8
      Runtime/ui/renderer/allocator.meta
  32. 11
      Runtime/ui/renderer/allocator/generic_list.cs.meta
  33. 11
      Runtime/ui/renderer/allocator/debug.cs.meta
  34. 11
      Runtime/ui/renderer/allocator/pool_object.cs.meta
  35. 11
      Runtime/ui/renderer/allocator/uipath_cache_manager.cs.meta
  36. 78
      Runtime/ui/renderer/allocator/debug.cs
  37. 51
      Runtime/ui/renderer/allocator/generic_list.cs
  38. 106
      Runtime/ui/renderer/allocator/pool_object.cs
  39. 54
      Runtime/ui/renderer/allocator/uipath_cache_manager.cs
  40. 8
      Runtime/ui/renderer/cmdbufferCanvas.meta
  41. 27
      Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs
  42. 11
      Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs.meta
  43. 8
      Runtime/ui/renderer/cmdbufferCanvas/rendering.meta
  44. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs.meta
  45. 1001
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
  46. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs.meta
  47. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs.meta
  48. 39
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs
  49. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs.meta
  50. 232
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs
  51. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs.meta
  52. 100
      Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs
  53. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs.meta
  54. 141
      Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs
  55. 11
      Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs.meta
  56. 8
      Runtime/ui/renderer/common.meta
  57. 308
      Runtime/ui/renderer/common/base_canvas.cs
  58. 11
      Runtime/ui/renderer/common/base_canvas.cs.meta
  59. 80
      Runtime/ui/renderer/common/color.cs
  60. 11
      Runtime/ui/renderer/common/color.cs.meta
  61. 415
      Runtime/ui/renderer/common/draw_cmd.cs
  62. 11
      Runtime/ui/renderer/common/draw_cmd.cs.meta
  63. 8
      Runtime/ui/renderer/common/geometry.meta
  64. 11
      Runtime/ui/renderer/common/geometry/offset.cs.meta
  65. 11
      Runtime/ui/renderer/common/geometry/rect.cs.meta
  66. 8
      Runtime/ui/renderer/common/geometry/matrix.meta
  67. 11
      Runtime/ui/renderer/common/geometry/mesh_mesh.cs.meta
  68. 8
      Runtime/ui/renderer/common/geometry/path.meta
  69. 11
      Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs.meta
  70. 11
      Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs.meta
  71. 761
      Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs
  72. 572
      Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs
  73. 147
      Runtime/ui/renderer/common/geometry/mesh_mesh.cs
  74. 25
      Runtime/ui/renderer/common/geometry/offset.cs
  75. 11
      Runtime/ui/renderer/common/geometry/path/path.cs.meta
  76. 11
      Runtime/ui/renderer/common/geometry/path/path_cache.cs.meta
  77. 11
      Runtime/ui/renderer/common/geometry/path/path_utils.cs.meta
  78. 11
      Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs.meta
  79. 422
      Runtime/ui/renderer/common/geometry/path/path.cs
  80. 563
      Runtime/ui/renderer/common/geometry/path/path_cache.cs
  81. 323
      Runtime/ui/renderer/common/geometry/path/path_utils.cs
  82. 261
      Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs
  83. 227
      Runtime/ui/renderer/common/geometry/rect.cs
  84. 171
      Runtime/ui/renderer/common/paint.cs
  85. 11
      Runtime/ui/renderer/common/paint.cs.meta
  86. 322
      Runtime/ui/renderer/common/picture.cs
  87. 11
      Runtime/ui/renderer/common/picture.cs.meta
  88. 53
      Runtime/ui/renderer/common/utils.cs
  89. 11
      Runtime/ui/renderer/common/utils.cs.meta
  90. 8
      Runtime/ui/renderer/compositeCanvas.meta
  91. 11
      Runtime/ui/renderer/compositeCanvas/compositing.cs.meta

1
Runtime/editor/rasterizer.cs


this._fireNextFrameCallbackIfPresent();
return true;
}
return false;
}
}

3
Runtime/rendering/view.cs


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

16
Runtime/ui/matrix.cs


return prod == 0; // if prod is NaN, this check will return false
}
static byte[] _scalar_as_2s_compliment_vars = new byte[4];
static unsafe int GetBytesToInt32(float value) {
var intVal = *(int*) &value;
fixed (byte* b = _scalar_as_2s_compliment_vars) {
*((int*) b) = intVal;
}
fixed (byte* pbyte = &_scalar_as_2s_compliment_vars[0]) {
return *((int*) pbyte);
}
}
var result = BitConverter.ToInt32(BitConverter.GetBytes(x), 0);
var result = GetBytesToInt32(x);
if (result < 0) {
result &= 0x7FFFFFFF;
result = -result;

28
Runtime/ui/painting/path.cs


PathCache _cache;
static uint pathGlobalKey = 0;
uint _pathKey = 0;
public uint pathKey {
get {
return this._pathKey;
}
}
public List<float> commands => this._commands;
public override string ToString() {
var sb = new StringBuilder("Path: count = " + this._commands.Count);

return sb.ToString();
}
public void resetAll() {
this._reset();
}
void _reset() {
this._commands.Clear();
this._commandx = 0;

this._maxX = float.MinValue;
this._maxY = float.MinValue;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._commandx = x;
this._commandy = y;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._commandx = x;
this._commandy = y;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._commandx = x3;
this._commandy = y3;
this._pathKey = pathGlobalKey++;
this._pathKey = pathGlobalKey++;
this._cache = null;
}

this._pathKey = pathGlobalKey++;
this._cache = null;
}

54
Runtime/ui/painting/shader.cs


public static Gradient linear(
Offset start, Offset end, List<Color> colors,
List<float> colorStops = null, TileMode tileMode = TileMode.clamp,
Matrix3 matrix = null) {
uiMatrix3? matrix = null) {
D.assert(PaintingUtils._offsetIsValid(start));
D.assert(PaintingUtils._offsetIsValid(end));
D.assert(colors != null && colors.Count >= 2);

public static Gradient radial(
Offset center, float radius, List<Color> colors,
List<float> colorStops = null, TileMode tileMode = TileMode.clamp,
Matrix3 matrix = null) {
uiMatrix3? matrix = null) {
D.assert(PaintingUtils._offsetIsValid(center));
D.assert(colors != null && colors.Count >= 2);

Offset center, List<Color> colors,
List<float> colorStops = null, TileMode tileMode = TileMode.clamp,
float startAngle = 0.0f, float endAngle = Mathf.PI * 2,
Matrix3 matrix = null) {
uiMatrix3? matrix = null) {
D.assert(PaintingUtils._offsetIsValid(center));
D.assert(colors != null && colors.Count >= 2);
D.assert(startAngle < endAngle);

public _LinearGradient(
Offset start, Offset end, List<Color> colors,
List<float> colorStops, TileMode tileMode,
Matrix3 matrix = null) {
uiMatrix3? matrix = null) {
this.start = start;
this.end = end;
this.colors = colors;

public readonly List<Color> colors;
public readonly List<float> colorStops;
public readonly TileMode tileMode;
public readonly Matrix3 matrix;
public readonly Matrix3 ptsToUnit;
public readonly uiMatrix3? matrix;
public readonly uiMatrix3 ptsToUnit;
public readonly Image gradientTex;
public Color leftColor {

get { return this.colors[this.colors.Count - 1]; }
}
public Matrix3 getGradientMat(Matrix3 mat) {
public uiMatrix3 getGradientMat(uiMatrix3 mat) {
mat.postConcat(this.matrix);
mat.postConcat(this.matrix.Value);
}
mat.postConcat(this.ptsToUnit);

static Matrix3 ptsToUnitMatrix(Offset start, Offset end) {
static uiMatrix3 ptsToUnitMatrix(Offset start, Offset end) {
var matrix = Matrix3.I();
var matrix = uiMatrix3.I();
matrix.setSinCos(-vec.dy, vec.dx, start.dx, start.dy);
matrix.postTranslate(-start.dx, -start.dy);
matrix.postScale(inv, inv);

public _RadialGradient(
Offset center, float radius, List<Color> colors,
List<float> colorStops = null, TileMode tileMode = TileMode.clamp,
Matrix3 matrix = null
uiMatrix3? matrix = null
) {
this.center = center;
this.radius = radius;

public readonly List<Color> colors;
public readonly List<float> colorStops;
public readonly TileMode tileMode;
public readonly Matrix3 matrix;
public readonly Matrix3 ptsToUnit;
public readonly uiMatrix3? matrix;
public readonly uiMatrix3 ptsToUnit;
public readonly Image gradientTex;
public Color leftColor {

get { return this.colors[this.colors.Count - 1]; }
}
public Matrix3 getGradientMat(Matrix3 mat) {
public uiMatrix3 getGradientMat(uiMatrix3 mat) {
mat.postConcat(this.matrix);
mat.postConcat(this.matrix.Value);
}
mat.postConcat(this.ptsToUnit);

static Matrix3 radToUnitMatrix(Offset center, float radius) {
static uiMatrix3 radToUnitMatrix(Offset center, float radius) {
var matrix = Matrix3.I();
var matrix = uiMatrix3.I();
matrix.setTranslate(-center.dx, -center.dy);
matrix.postScale(inv, inv);
return matrix;

Offset center, List<Color> colors,
List<float> colorStops = null, TileMode tileMode = TileMode.clamp,
float startAngle = 0.0f, float endAngle = Mathf.PI * 2,
Matrix3 matrix = null
uiMatrix3? matrix = null
) {
this.center = center;
this.colors = colors;

this.bias = -t0;
this.scale = 1f / (t1 - t0);
var ptsToUnit = Matrix3.I();
var ptsToUnit = uiMatrix3.I();
ptsToUnit.setTranslate(-center.dx, -center.dy);
this.ptsToUnit = ptsToUnit;

public readonly TileMode tileMode;
public readonly float startAngle;
public readonly float endAngle;
public readonly Matrix3 matrix;
public readonly Matrix3 ptsToUnit;
public readonly uiMatrix3? matrix;
public readonly uiMatrix3 ptsToUnit;
public readonly Image gradientTex;
public readonly float bias;
public readonly float scale;

get { return this.colors[this.colors.Count - 1]; }
}
public Matrix3 getGradientMat(Matrix3 mat) {
public uiMatrix3 getGradientMat(uiMatrix3 mat) {
mat.postConcat(this.matrix);
mat.postConcat(this.matrix.Value);
}
mat.postConcat(this.ptsToUnit);

public class ImageShader : PaintShader {
public ImageShader(Image image,
TileMode tileMode = TileMode.clamp, Matrix3 matrix = null) {
TileMode tileMode = TileMode.clamp, uiMatrix3? matrix = null) {
this.image = image;
this.tileMode = tileMode;
this.matrix = matrix;

public readonly TileMode tileMode;
public readonly Matrix3 matrix;
public readonly uiMatrix3? matrix;
public Matrix3 getShaderMat(Matrix3 mat) {
public uiMatrix3 getShaderMat(uiMatrix3 mat) {
mat.postConcat(this.matrix);
mat.postConcat(this.matrix.Value);
}
mat.postScale(1f / this.image.width, 1f / this.image.height);

101
Runtime/ui/painting/shadow_utils.cs


namespace Unity.UIWidgets.ui {
static class ShadowUtils {
public static bool kUseFastShadow = false;
public const bool kUseFastShadow = false;
public const float kAmbientHeightFactor = 1.0f / 128.0f;
public const float kAmbientGeomFactor = 64.0f;
const float kAmbientHeightFactor = 1.0f / 128.0f;
const float kAmbientGeomFactor = 64.0f;
public const float kBlurSigmaScale = 0.57735f;
const float kBlurSigmaScale = 0.57735f;
public const float kMaxAmbientRadius = 300 * kAmbientHeightFactor * kAmbientGeomFactor;
const float kMaxAmbientRadius = 300 * kAmbientHeightFactor * kAmbientGeomFactor;
public static float divideAndPin(float numer, float denom, float min, float max) {
static float divideAndPin(float numer, float denom, float min, float max) {
public static float ambientBlurRadius(float height) {
static float ambientBlurRadius(float height) {
public static float ambientRecipAlpha(float height) {
static float ambientRecipAlpha(float height) {
public static float spotBlurRadius(float occluderZ, float lightZ, float lightRadius) {
static float spotBlurRadius(float occluderZ, float lightZ, float lightRadius) {
public static void getSpotParams(float occluderZ, float lightX, float lightY, float lightZ,
static void getSpotParams(float occluderZ, float lightX, float lightY, float lightZ,
float lightRadius,
ref float blurRadius, ref float scale, ref Vector2 translate) {
float zRatio = divideAndPin(occluderZ, lightZ - occluderZ, 0.0f, 0.95f);

}
public static float convertRadiusToSigma(float radius) {
static float convertRadiusToSigma(float radius) {
public static void computeTonalColors(Color inAmbientColor, Color inSpotColor,
ref Color outAmbientColor, ref Color outSpotColor) {
outAmbientColor = Color.fromARGB(inAmbientColor.alpha, 0, 0, 0);
public static void computeTonalColors(uiColor inAmbientColor, uiColor inSpotColor,
ref uiColor? outAmbientColor, ref uiColor? outSpotColor) {
outAmbientColor = uiColor.fromARGB(inAmbientColor.alpha, 0, 0, 0);
public static bool getSpotShadowTransform(Vector3 lightPos, float lightRadius, Matrix3 ctm,
static readonly Matrix3 _toHomogeneous = Matrix3.I();
static bool getSpotShadowTransform(Vector3 lightPos, float lightRadius, Matrix3 ctm,
Vector3 zPlaneParams, Rect pathBounds, Matrix3 shadowTransform, ref float radius) {
float heightFunc(float x, float y) {
return zPlaneParams.x * x + zPlaneParams.y * y + zPlaneParams.z;

h0.y / h2.z, h1.y / h2.z, h2.y / h2.z,
h0.z / h2.z, h1.z / h2.z, 1);
Matrix3 toHomogeneous = Matrix3.I();
toHomogeneous.setAll(xScale, 0, -xScale * pathBounds.left - 1,
_toHomogeneous.setAll(xScale, 0, -xScale * pathBounds.left - 1,
shadowTransform.preConcat(toHomogeneous);
shadowTransform.preConcat(_toHomogeneous);
radius = spotBlurRadius(occluderHeight, lightPos.z, lightRadius);
}

static readonly Path _devSpacePath = new Path();
float lightRadius, Color ambientColor, Color spotColor, int flags) {
float lightRadius, uiColor ambientColor, uiColor spotColor, int flags) {
if (kUseFastShadow) {
drawShadowFast(canvas, path, zPlaneParams, devLightPos, lightRadius, ambientColor, spotColor, flags);
}

}
//cached variables
static readonly Paint _shadowPaint = new Paint();
static readonly Matrix3 _shadowMatrix = Matrix3.I();
float lightRadius, Color ambientColor, Color spotColor, int flags) {
float lightRadius, uiColor ambientColor, uiColor spotColor, int flags) {
Path devSpacePath = path.transform(viewMatrix);
_devSpacePath.resetAll();
_devSpacePath.addPath(path, viewMatrix);
Paint paint = new Paint {color = ambientColor, strokeWidth = strokeWidth, style = PaintingStyle.fill};
//Paint paint = new Paint {color = ambientColor, strokeWidth = strokeWidth, style = PaintingStyle.fill};
_shadowPaint.color = new Color(ambientColor.value);
_shadowPaint.strokeWidth = strokeWidth;
_shadowPaint.style = PaintingStyle.fill;
canvas.setMatrix(Matrix3.I());
_shadowMatrix.reset();
canvas.setMatrix(_shadowMatrix);
paint.maskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
canvas.drawPath(devSpacePath, paint);
_shadowPaint.maskFilter = MaskFilter.blur(BlurStyle.normal, sigma);
canvas.drawPath(_devSpacePath, _shadowPaint);
Matrix3 shadowMatrix = Matrix3.I();
//Matrix3 shadowMatrix = Matrix3.I();
shadowMatrix, ref radius)) {
_shadowMatrix, ref radius)) {
canvas.setMatrix(shadowMatrix);
Paint paint2 = new Paint {color = spotColor};
canvas.setMatrix(_shadowMatrix);
_shadowPaint.color = new Color(spotColor.value);
_shadowPaint.strokeWidth = 0;
_shadowPaint.style = PaintingStyle.fill;
paint2.maskFilter = MaskFilter.blur(BlurStyle.normal, sigma2);
canvas.drawPath(path, paint2);
_shadowPaint.maskFilter = MaskFilter.blur(BlurStyle.normal, sigma2);
canvas.drawPath(path, _shadowPaint);
_shadowPaint.maskFilter = null;
float lightRadius, Color ambientColor, Color spotColor, int flags) {
float lightRadius, uiColor ambientColor, uiColor spotColor, int flags) {
Matrix3 viewMatrix = canvas.getTotalMatrix();
//ambient light

float strokeWidth = 0.5f * (devSpaceOutset - blurRadius);
Paint paint = new Paint {color = ambientColor, strokeWidth = strokeWidth, style = PaintingStyle.fill};
canvas.drawPath(path, paint);
//Paint paint = new Paint {color = ambientColor, strokeWidth = strokeWidth, style = PaintingStyle.fill};
_shadowPaint.color = new Color(ambientColor.value);
_shadowPaint.strokeWidth = strokeWidth;
_shadowPaint.style = PaintingStyle.fill;
canvas.drawPath(path, _shadowPaint);
Matrix3 shadowMatrix = Matrix3.I();
shadowMatrix, ref radius)) {
_shadowMatrix, ref radius)) {
canvas.setMatrix(shadowMatrix);
Paint paint2 = new Paint {color = spotColor};
canvas.drawPath(path, paint2);
canvas.setMatrix(_shadowMatrix);
//Paint paint2 = new Paint {color = spotColor};
_shadowPaint.color = new Color(spotColor.value);
_shadowPaint.strokeWidth = 0;
_shadowPaint.style = PaintingStyle.fill;
canvas.drawPath(path, _shadowPaint);
canvas.restore();
}

159
Runtime/ui/painting/txt/mesh_generator.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
class MeshKey : IEquatable<MeshKey> {
public readonly long textBlobId;
public readonly float scale;
class MeshKey : PoolObject, IEquatable<MeshKey> {
public long textBlobId;
public float scale;
public MeshKey(long textBlobId, float scale) {
this.textBlobId = textBlobId;
this.scale = scale;
public MeshKey() {
}
public static MeshKey create(long textBlobId, float scale) {
var newKey = ObjectPool<MeshKey>.alloc();
newKey.textBlobId = textBlobId;
newKey.scale = scale;
return newKey;
}
public bool Equals(MeshKey other) {

}
}
class MeshInfo {
public readonly MeshKey key;
public readonly long textureVersion;
public readonly MeshMesh mesh;
class MeshInfo : PoolObject {
public MeshKey key;
public long textureVersion;
public uiMeshMesh mesh;
public MeshInfo(MeshKey key, MeshMesh mesh, long textureVersion, int timeToLive = 5) {
this.mesh = mesh;
this.key = key;
this.textureVersion = textureVersion;
this.touch(timeToLive);
public MeshInfo() {
}
public static MeshInfo create(MeshKey key, uiMeshMesh mesh, long textureVersion, int timeToLive = 5) {
var meshInfo = ObjectPool<MeshInfo>.alloc();
meshInfo.mesh = mesh;
meshInfo.key = key;
meshInfo.textureVersion = textureVersion;
meshInfo.touch(timeToLive);
return meshInfo;
}
public override void clear() {
ObjectPool<MeshKey>.release(this.key);
ObjectPool<uiMeshMesh>.release(this.mesh);
}
public long timeToLive {

}
class TextBlobMesh {
class TextBlobMesh : PoolObject {
public readonly TextBlob textBlob;
public readonly float scale;
public readonly Matrix3 matrix;
public TextBlob textBlob;
public float scale;
public uiMatrix3 matrix;
MeshMesh _mesh;
uiMeshMesh _mesh;
public TextBlobMesh(TextBlob textBlob, float scale, Matrix3 matrix) {
this.textBlob = textBlob;
this.scale = scale;
this.matrix = matrix;
public TextBlobMesh() {
}
public override void clear() {
ObjectPool<uiMeshMesh>.release(this._mesh);
this._mesh = null;
this._resolved = false;
}
public static TextBlobMesh create(TextBlob textBlob, float scale, uiMatrix3 matrix) {
TextBlobMesh newMesh = ObjectPool<TextBlobMesh>.alloc();
newMesh.textBlob = textBlob;
newMesh.scale = scale;
newMesh.matrix = matrix;
return newMesh;
}
public static long frameCount {

public static int meshCount {
get { return _meshes.Count; }
}
static readonly List<MeshKey> _keysToRemove = new List<MeshKey>();
static List<MeshKey> _keysToRemove = new List<MeshKey>();
_keysToRemove.Clear();
foreach (var info in _meshes.Values) {
if (info.timeToLive < _frameCount) {
_keysToRemove.Add(info.key);
D.assert(_keysToRemove.Count == 0);
foreach (var key in _meshes.Keys) {
if (_meshes[key].timeToLive < _frameCount) {
_keysToRemove.Add(key);
foreach (var key in _keysToRemove) {
foreach (var key in _keysToRemove)
{
ObjectPool<MeshInfo>.release(_meshes[key]);
_keysToRemove.Clear();
public MeshMesh resolveMesh() {
public uiMeshMesh resolveMesh() {
if (this._resolved) {
return this._mesh;
}

var style = this.textBlob.style;
var key = new MeshKey(this.textBlob.instanceId, this.scale);
var key = MeshKey.create(this.textBlob.instanceId, this.scale);
_meshes.TryGetValue(key, out var meshInfo);
if (meshInfo != null && meshInfo.textureVersion == fontInfo.textureVersion) {
ObjectPool<MeshKey>.release(key);
meshInfo.touch();
this._mesh = meshInfo.mesh.transform(this.matrix);
return this._mesh;
}
var vert = new List<Vector3>();
var tri = new List<int>();
var uvCoord = new List<Vector2>();
var vert = ObjectPool<uiList<Vector3>>.alloc();
var tri = ObjectPool<uiList<int>>.alloc();
var uvCoord = ObjectPool<uiList<Vector2>>.alloc();
var metrics = FontMetrics.fromFont(font, style.UnityFontSize);
var minMaxRect = EmojiUtils.getMinMaxRect(style.fontSize, metrics.ascent, metrics.descent);
var minX = minMaxRect.left;

vert.Add(new Vector3(pos + maxX, minY, 0));
vert.Add(new Vector3(pos + maxX, maxY, 0));
vert.Add(new Vector3(pos + minX, maxY, 0));
tri.Add(baseIndex);
tri.Add(baseIndex + 1);
tri.Add(baseIndex + 2);

uvCoord.Add(uvRect.bottomRight.toVector());
uvCoord.Add(uvRect.topRight.toVector());
uvCoord.Add(uvRect.topLeft.toVector());
MeshMesh meshMesh = new MeshMesh(null, vert, tri, uvCoord);
_meshes[key] = new MeshInfo(key, meshMesh, 0);
uiMeshMesh meshMesh = uiMeshMesh.create(null, vert, tri, uvCoord);
if (_meshes.ContainsKey(key)) {
ObjectPool<MeshInfo>.release(_meshes[key]);
_meshes.Remove(key);
}
_meshes[key] = MeshInfo.create(key, meshMesh, 0);
_meshes.TryGetValue(key, out var meshInfo);
if (meshInfo != null && meshInfo.textureVersion == fontInfo.textureVersion) {
meshInfo.touch();
this._mesh = meshInfo.mesh.transform(this.matrix);
return this._mesh;
}
var vertices = new List<Vector3>(length * 4);
var triangles = new List<int>(length * 6);
var uv = new List<Vector2>(length * 4);
var vertices = ObjectPool<uiList<Vector3>>.alloc();
vertices.SetCapacity(length * 4);
var triangles = ObjectPool<uiList<int>>.alloc();
triangles.SetCapacity(length * 6);
var uv = ObjectPool<uiList<Vector2>>.alloc();
uv.SetCapacity(length * 4);
for (int charIndex = 0; charIndex < length; ++charIndex) {
var ch = text[charIndex + this.textBlob.textOffset];
// first char as origin for mesh position

if (vertices.Count == 0) {
this._mesh = null;
ObjectPool<uiList<Vector3>>.release(vertices);
ObjectPool<uiList<Vector2>>.release(uv);
ObjectPool<uiList<int>>.release(triangles);
ObjectPool<MeshKey>.release(key);
MeshMesh mesh = vertices.Count > 0 ? new MeshMesh(null, vertices, triangles, uv) : null;
_meshes[key] = new MeshInfo(key, mesh, fontInfo.textureVersion);
uiMeshMesh mesh = vertices.Count > 0 ? uiMeshMesh.create(null, vertices, triangles, uv) : null;
if (_meshes.ContainsKey(key)) {
ObjectPool<MeshInfo>.release(_meshes[key]);
_meshes.Remove(key);
}
_meshes[key] = MeshInfo.create(key, mesh, fontInfo.textureVersion);
this._mesh = mesh.transform(this.matrix);
return this._mesh;

2
Runtime/ui/painting/txt/text_blob.cs


return result;
}
}
}
}

2
Runtime/widgets/binding.cs


this.addPersistentFrameCallback((duration) => {
TextBlobMesh.tickNextFrame();
TessellationGenerator.tickNextFrame();
uiTessellationGenerator.tickNextFrame();
uiPathCacheManager.tickNextFrame();
});
}

2
Samples/UIWidgetSample/NavigationSample.cs


using System.Collections.Generic;
using Unity.UIWidgets.animation;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.material;
using DialogUtils = Unity.UIWidgets.widgets.DialogUtils;
using TextStyle = Unity.UIWidgets.painting.TextStyle;
namespace UIWidgetsSample {

9
Samples/UIWidgetSample/TextInput.unity


m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.37311947, g: 0.38074, b: 0.35872698, a: 1}
m_IndirectSpecularColor: {r: 0.37311953, g: 0.38074, b: 0.35872698, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &3
LightmapSettings:

m_EditorClassIdentifier:
m_UiScaleMode: 0
m_ReferencePixelsPerUnit: 100
m_ScaleFactor: 1
m_ScaleFactor: 1.5
m_ReferenceResolution: {x: 800, y: 600}
m_ScreenMatchMode: 0
m_MatchWidthOrHeight: 0

width: 1
height: 1
devicePixelRatioOverride: 0
antiAliasingOverride: 4
--- !u!222 &1142533066
CanvasRenderer:
m_ObjectHideFlags: 0

width: 1
height: 1
devicePixelRatioOverride: 4
antiAliasingOverride: 4
--- !u!222 &1354314694
CanvasRenderer:
m_ObjectHideFlags: 0

m_GameObject: {fileID: 1387978526}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e9bc91696c1584e11b23dca1a9e3cde3, type: 3}
m_Script: {fileID: 11500000, guid: 9c5c86936ca864ae684720ddcd50d759, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}

width: 1
height: 1
devicePixelRatioOverride: 0
antiAliasingOverride: 0
--- !u!222 &1387978529
CanvasRenderer:
m_ObjectHideFlags: 0

240
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs


using System;
using Unity.UIWidgets.painting;
using UnityEngine;
using UnityEngine.Rendering;

_stencilMat = new Material(stencilShader) {hideFlags = HideFlags.HideAndDontSave};
_filterMat = new Material(filterShader) {hideFlags = HideFlags.HideAndDontSave};
}
static readonly int _viewportId = Shader.PropertyToID("_viewport");
static readonly int _alphaId = Shader.PropertyToID("_alpha");
static readonly int _colorId = Shader.PropertyToID("_color");

static readonly int _mfImgIncId = Shader.PropertyToID("_mf_imgInc");
static readonly int _mfKernelId = Shader.PropertyToID("_mf_kernel");
static Vector4 _colorToVector4(uiColor c) {
return new Vector4(
c.red / 255f,
c.green / 255f,
c.blue / 255f,
c.alpha / 255f
);
}
static Vector4 _colorToVector4(Color c) {
return new Vector4(
c.red / 255f,

);
}
static Matrix3 _getShaderMatBase(PictureFlusher.State state, Matrix3 meshMatrix) {
if (state.matrix == meshMatrix) {
return Matrix3.I();
static uiMatrix3 _getShaderMatBase(PictureFlusher.State state, uiMatrix3? meshMatrix) {
if (uiMatrix3.equals(state.matrix, meshMatrix)) {
return uiMatrix3.I();
}
if (meshMatrix == null) {

return Matrix3.concat(state.invMatrix, meshMatrix);
return uiMatrix3.concat(state.invMatrix, meshMatrix.Value);
PictureFlusher.RenderLayer layer, Paint paint, Matrix3 meshMatrix, float alpha,
out int pass, out MaterialPropertyBlock props) {
PictureFlusher.RenderLayer layer, uiPaint paint, uiMatrix3? meshMatrix, float alpha,
out int pass, out MaterialPropertyBlockWrapper props) {
props = new MaterialPropertyBlock();
props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
props.SetVector(_viewportId, viewport);
props.SetFloat(_alphaId, alpha);

}
}
public static PictureFlusher.CmdDraw convexFill(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh) {
public static PictureFlusher.CmdDraw convexFill(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh) {
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw fill0(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.CmdDraw fill0(PictureFlusher.RenderLayer layer, uiMeshMesh mesh) {
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw fill1(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh) {
public static PictureFlusher.CmdDraw fill1(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh) {
return new PictureFlusher.CmdDraw {
mesh = mesh.boundsMesh,
pass = pass,
material = mat,
properties = props,
};
var ret = PictureFlusher.CmdDraw.create(
mesh: mesh.boundsMesh,
pass: pass,
material: mat,
properties: props
);
ObjectPool<uiMeshMesh>.release(mesh);
return ret;
public static PictureFlusher.CmdDraw stroke0(PictureFlusher.RenderLayer layer, Paint paint,
float alpha, MeshMesh mesh) {
public static PictureFlusher.CmdDraw stroke0(PictureFlusher.RenderLayer layer, uiPaint paint,
float alpha, uiMeshMesh mesh) {
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw stroke1(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.CmdDraw stroke1(PictureFlusher.RenderLayer layer, uiMeshMesh mesh) {
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
PictureFlusher.RenderLayer layer, MeshMesh mesh) {
PictureFlusher.RenderLayer layer, uiMeshMesh mesh) {
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw stencil0(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.CmdDraw stencil0(PictureFlusher.RenderLayer layer, uiMeshMesh mesh) {
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw stencil1(PictureFlusher.RenderLayer layer, MeshMesh mesh) {
public static PictureFlusher.CmdDraw stencil1(PictureFlusher.RenderLayer layer, uiMeshMesh mesh) {
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw tex(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, Image image) {
public static PictureFlusher.CmdDraw tex(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh, Image image) {
var mat = _texMat.getMaterial(paint.blendMode, layer.ignoreClip);
_getShaderPassAndProps(layer, paint, mesh.matrix, 1.0f, out var pass, out var props);

return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
image = image, // keep a reference to avoid GC.
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props,
image: image // keep a reference to avoid GC.
);
public static PictureFlusher.CmdDraw texRT(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, PictureFlusher.RenderLayer renderLayer) {
public static PictureFlusher.CmdDraw texRT(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh, PictureFlusher.RenderLayer renderLayer) {
return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
layer = renderLayer,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props,
layerId: renderLayer.rtID
);
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, Texture tex) {
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh, Texture tex) {
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, Paint paint,
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, uiPaint paint,
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, Paint paint,
MeshMesh mesh, TextBlobMesh textMesh, Texture tex) {
public static PictureFlusher.CmdDraw texAlpha(PictureFlusher.RenderLayer layer, uiPaint paint,
uiMeshMesh mesh, TextBlobMesh textMesh, Texture tex) {
var mat = _texMat.getMaterial(paint.blendMode, layer.ignoreClip);
var meshMatrix = mesh != null ? mesh.matrix : textMesh.matrix;
_getShaderPassAndProps(layer, paint, meshMatrix, 1.0f, out var pass, out var props);

return new PictureFlusher.CmdDraw {
mesh = mesh,
textMesh = textMesh,
pass = pass,
material = mat,
properties = props,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
textMesh: textMesh,
pass: pass,
material: mat,
properties: props
);
public static PictureFlusher.CmdDraw maskFilter(PictureFlusher.RenderLayer layer, MeshMesh mesh,
public static PictureFlusher.CmdDraw maskFilter(PictureFlusher.RenderLayer layer, uiMeshMesh mesh,
var props = new MaterialPropertyBlock();
var props = ObjectPool<MaterialPropertyBlockWrapper>.alloc();
props.SetVector(_viewportId, viewport);
props.SetFloat(_mfRadiusId, radius);

return new PictureFlusher.CmdDraw {
mesh = mesh,
pass = pass,
material = mat,
properties = props,
layer = renderLayer,
};
return PictureFlusher.CmdDraw.create(
mesh: mesh,
pass: pass,
material: mat,
properties: props,
layerId: renderLayer.rtID
);
}
}
}

174
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
class ClipElement {
public readonly int saveCount;
public readonly MeshMesh mesh;
public readonly bool convex;
public readonly bool isRect;
public Rect rect { get; private set; }
class ClipElement : PoolObject {
public int saveCount;
public uiMeshMesh mesh;
public bool convex;
public bool isRect;
public uiRect? rect { get; private set; }
Rect _bound;
Matrix3 _invMat;
uiRect _bound;
uiMatrix3? _invMat;
public ClipElement(int saveCount, Path path, Matrix3 matrix, float scale) {
this.saveCount = saveCount;
public ClipElement() {
}
var pathCache = path.flatten(scale);
this.mesh = pathCache.getFillMesh(out this.convex).transform(matrix);
public override void clear() {
ObjectPool<uiMeshMesh>.release(this.mesh);
this.saveCount = 0;
this.mesh = null;
this.convex = false;
this.isRect = false;
this._genId = 0;
this._isIntersectionOfRects = false;
this._invMat = null;
}
var vertices = this.mesh.vertices;
if (this.convex && vertices.Count == 4 && matrix.rectStaysRect() &&
public static ClipElement create(int saveCount, uiPath uiPath, uiMatrix3 matrix, float scale) {
ClipElement newElement = ObjectPool<ClipElement>.alloc();
newElement.saveCount = saveCount;
var pathCache = uiPath.flatten(scale);
var fillMesh = pathCache.getFillMesh(out newElement.convex);
newElement.mesh = fillMesh.transform(matrix);
var vertices = newElement.mesh.vertices;
if (newElement.convex && vertices.Count == 4 && matrix.rectStaysRect() &&
this.isRect = true;
this.rect = this.mesh.bounds;
newElement.isRect = true;
newElement.rect = newElement.mesh.bounds;
this.isRect = false;
this.rect = null;
newElement.isRect = false;
newElement.rect = null;
return newElement;
public void setRect(Rect rect) {
public void setRect(uiRect rect) {
D.assert(this.isRect && this.rect.contains(rect));
D.assert(this.isRect && uiRectHelper.contains(this.rect.Value, rect));
this.rect = rect;
}

this._bound = Rect.zero;
this._bound = uiRectHelper.zero;
}
public void updateBoundAndGenID(ClipElement prior) {

if (this.isRect) {
this._bound = this.rect;
this._bound = this.rect.Value;
if (prior == null || prior.isIntersectionOfRects()) {
this._isIntersectionOfRects = true;
}

}
if (prior != null) {
this._bound = this._bound.intersect(prior.getBound());
this._bound = uiRectHelper.intersect(this._bound, prior.getBound());
}
if (this._bound.isEmpty) {

return this.getGenID() == ClipStack.emptyGenID;
}
public Rect getBound() {
public uiRect getBound() {
D.assert(ClipStack.invalidGenID != this._genId);
return this._bound;
}

return this._genId;
}
bool _convexContains(Rect rect) {
bool _convexContains(uiRect rect) {
if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
return false;
}

}
public bool contains(Rect rect) {
public bool contains(uiRect rect) {
return this.rect.contains(rect);
return uiRectHelper.contains(this.rect.Value, rect);
if (this.mesh.matrix != null && !this.mesh.matrix.isIdentity()) {
if (this.mesh.matrix != null && !this.mesh.matrix.Value.isIdentity()) {
this._invMat = Matrix3.I();
this.mesh.matrix.invert(this._invMat); // ignore if not invertible for now.
this._invMat = this.mesh.matrix.Value.invert();
rect = this._invMat.mapRect(rect);
rect = this._invMat.Value.mapRect(rect);
}
return this._convexContains(rect);

}
}
class ClipStack {
class ClipStack : PoolObject {
static uint _genId = wideOpenGenID;
public static uint getNextGenID() {

public const uint wideOpenGenID = 2;
public readonly List<ClipElement> stack = new List<ClipElement>();
public readonly List<ClipElement> stack = new List<ClipElement>(32);
Rect _bound;
uiRect _bound;
public static ClipStack create() {
return ObjectPool<ClipStack>.alloc();
}
public override void clear() {
this._saveCount = 0;
this._lastElement = null;
foreach (var clipelement in this.stack) {
ObjectPool<ClipElement>.release(clipelement);
}
this.stack.Clear();
}
public void save() {
this._saveCount++;
}

if (this._lastElement.saveCount <= saveCount) {
break;
}
var lastelement = this.stack[this.stack.Count - 1];
ObjectPool<ClipElement>.release(lastelement);
this.stack.RemoveAt(this.stack.Count - 1);
this._lastElement = this.stack.Count == 0 ? null : this.stack[this.stack.Count - 1];

public void clipPath(Path path, Matrix3 matrix, float scale) {
var element = new ClipElement(this._saveCount, path, matrix, scale);
public void clipPath(uiPath uiPath, uiMatrix3 matrix, float scale) {
var element = ClipElement.create(this._saveCount, uiPath, matrix, scale);
this._pushElement(element);
}

if (prior.isEmpty()) {
ObjectPool<ClipElement>.release(element);
return;
}

var isectRect = prior.rect.intersect(element.rect);
var isectRect = uiRectHelper.intersect(prior.rect.Value, element.rect.Value);
ObjectPool<ClipElement>.release(element);
return;
}

ObjectPool<ClipElement>.release(element);
if (!prior.getBound().overlaps(element.getBound())) {
if (!uiRectHelper.overlaps(prior.getBound(), element.getBound())) {
ObjectPool<ClipElement>.release(element);
return;
}
}

element.updateBoundAndGenID(prior);
}
public void getBounds(out Rect bound, out bool isIntersectionOfRects) {
public void getBounds(out uiRect? bound, out bool isIntersectionOfRects) {
if (this._lastElement == null) {
bound = null;
isIntersectionOfRects = false;

}
}
class ReducedClip {
public readonly Rect scissor;
public readonly List<ClipElement> maskElements = new List<ClipElement>();
class ReducedClip : PoolObject {
public uiRect? scissor;
public List<ClipElement> maskElements = new List<ClipElement>();
return this.scissor != null && this.scissor.isEmpty;
return this.scissor != null && this.scissor.Value.isEmpty;
}
public ReducedClip() {
}
public override void clear() {
this.scissor = null;
this.maskElements.Clear();
this._lastElement = null;
}
public uint maskGenID() {

return element.getGenID();
}
public ReducedClip(ClipStack stack, Rect layerBounds, Rect queryBounds) {
Rect stackBounds;
public static ReducedClip create(ClipStack stack, uiRect layerBounds, uiRect queryBounds) {
ReducedClip clip = ObjectPool<ReducedClip>.alloc();
uiRect? stackBounds;
this.scissor = layerBounds;
return;
clip.scissor = layerBounds;
return clip;
stackBounds = layerBounds.intersect(stackBounds);
stackBounds = uiRectHelper.intersect(layerBounds, stackBounds.Value);
this.scissor = stackBounds;
return;
clip.scissor = stackBounds;
return clip;
queryBounds = stackBounds.intersect(queryBounds);
queryBounds = uiRectHelper.intersect(stackBounds.Value, queryBounds);
this.scissor = Rect.zero;
return;
clip.scissor = uiRectHelper.zero;
return clip;
this.scissor = queryBounds;
this._walkStack(stack, this.scissor);
clip.scissor = queryBounds;
clip._walkStack(stack, clip.scissor.Value);
return clip;
void _walkStack(ClipStack stack, Rect queryBounds) {
void _walkStack(ClipStack stack, uiRect queryBounds) {
foreach (var element in stack.stack) {
if (element.isRect) {
continue;

2
Runtime/ui/renderer/compositeCanvas/compositing.cs


return layer;
}
public void addRetained(Layer layer) {
if (this._currentLayer == null) {
return;

3
Runtime/ui/renderer/compositeCanvas/flow/clip_path_layer.cs


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

7
Runtime/ui/renderer/compositeCanvas/flow/clip_rect_layer.cs


this.paintBounds = childPaintBounds;
}
}
var canvas = context.canvas;
canvas.save();

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

5
Runtime/ui/renderer/compositeCanvas/flow/clip_rrect_layer.cs


public override void paint(PaintContext context) {
D.assert(this.needsPainting);
var canvas = context.canvas;
canvas.save();

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

5
Runtime/ui/renderer/compositeCanvas/flow/container_layer.cs


if (childPaintBounds == null || childPaintBounds.isEmpty) {
childPaintBounds = layer.paintBounds;
} else {
}
else {
childPaintBounds = childPaintBounds.expandToInclude(layer.paintBounds);
}
}

D.assert(this.needsPainting);
foreach (var layer in this._layers) {
if (layer.needsPainting) {
layer.paint(context);

8
Runtime/ui/renderer/compositeCanvas/flow/transform_layer.cs


Matrix3 inverseTransform = Matrix3.I();
if (this._transform.invert(inverseTransform)) {
context.cullRect = inverseTransform.mapRect(context.cullRect);
} else {
}
else {
context.cullRect = Rect.largest;
}

try {
canvas.concat(this._transform);
this.paintChildren(context);
} finally {
}
finally {
}
}

5
Runtime/ui/renderer/compositeCanvas/flow/texture_layer.cs


namespace Unity.UIWidgets.flow {
public class TextureLayer : Layer {
Offset _offset = Offset.zero;
public Offset offset {

if (this._texture == null) {
return;
}
}
var image = new Image(this._texture, noDispose: true);

}
}
}

5
Runtime/ui/renderer/compositeCanvas/flow/backdrop_filter_layer.cs


try {
this.paintChildren(context);
} finally {
}
finally {
}
}

21
Runtime/ui/renderer/compositeCanvas/flow/opacity_layer.cs


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.preTranslate(this._offset.dx, this._offset.dy); // TOOD: pre or post? https://github.com/flutter/engine/pull/7945
childMatrix.preTranslate(this._offset.dx,
this._offset.dy); // TOOD: pre or post? https://github.com/flutter/engine/pull/7945
var saveLayerBounds = this.paintBounds.shift(-this._offset).roundOut();
var saveLayerBounds = this.paintBounds.shift(-this._offset).roundOut();
try {
this.paintChildren(context);
}

15
Runtime/ui/renderer/compositeCanvas/flow/picture_layer.cs


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

try {
if (this._rasterCacheResult != null) {
this._rasterCacheResult.draw(canvas);
} else {
}
else {
} finally {
}
finally {
canvas.restore();
}
}

2
Runtime/ui/renderer/compositeCanvas/flow/layer_tree.cs


get { return this._devicePixelRatio; }
set { this._devicePixelRatio = value; }
}
int _antiAliasing;
public int antiAliasing {

46
Runtime/ui/renderer/compositeCanvas/flow/physical_shape_layer.cs


}
}
Paint _shadowPaint = new Paint();
public override void paint(PaintContext context) {
if (this._elevation != 0) {
drawShadow(context.canvas, this._path, this._shadow_color, this._elevation,

Paint paint = new Paint {color = this._color};
//todo: xingwei.zhu: process according to different clipBehavior, currently use antiAlias as default
context.canvas.drawPath(this._path, paint);
this._shadowPaint.color = this._color;
context.canvas.drawPath(this._path, this._shadowPaint);
context.canvas.save();
context.canvas.clipPath(this._path);

static Color _inAmbient;
static Color _inSpot;
static Color _ambientColor;
static Color _spotColor;
static Vector3 _zPlane = new Vector3();
static Vector3 _devLight = new Vector3();
const float kAmbientAlpha = 0.039f;
const float kLightHeight = 600f;
const float kLightRadius = 800f;
const float kSpotAlpha = ShadowUtils.kUseFastShadow ? 0.1f : 0.25f;
float kAmbientAlpha = 0.039f;
float kSpotAlpha = ShadowUtils.kUseFastShadow ? 0.1f : 0.25f;
float kLightHeight = 600f;
float kLightRadius = 800f;
_inAmbient = color.withAlpha((int) (kAmbientAlpha * color.alpha));
_inSpot = color.withAlpha((int) (kSpotAlpha * color.alpha));
_ambientColor = null;
_spotColor = null;
ShadowUtils.computeTonalColors(_inAmbient, _inSpot, ref _ambientColor, ref _spotColor);
_zPlane.Set(0, 0, dpr * elevation);
_devLight.Set(shadow_x, shadow_y, dpr * kLightHeight);
uiColor uicolor = uiColor.fromColor(color);
uiColor inAmbient = uicolor.withAlpha((int) (kAmbientAlpha * uicolor.alpha));
uiColor inSpot = uicolor.withAlpha((int) (kSpotAlpha * uicolor.alpha));
uiColor? ambientColor = null;
uiColor? spotColor = null;
ShadowUtils.computeTonalColors(inAmbient, inSpot, ref ambientColor, ref spotColor);
_zPlane,
_devLight,
new Vector3(0, 0, dpr * elevation),
new Vector3(shadow_x, shadow_y, dpr * kLightHeight),
_ambientColor,
_spotColor,
ambientColor.Value,
spotColor.Value,
0
);
}

1
Runtime/ui/renderer/compositeCanvas/flow/raster_cache.cs


canvas.concat(transform);
canvas.drawPicture(picture);
canvas.flush();
canvas.dispose();
return new RasterCacheResult(new Image(renderTexture), picture.paintBounds, devicePixelRatio);
}

3
Runtime/ui/renderer/compositeCanvas/flow/instrumentation.cs


}
var pb = new ParagraphBuilder(new ParagraphStyle { });
pb.addText("Current Frame Cost: " + costFrames[curFrame] * 1000 + "ms" + " ; Max(in last 120 frames): " + this.maxDelta() * 1000 + "ms");
pb.addText("Current Frame Cost: " + costFrames[curFrame] * 1000 + "ms" +
" ; Max(in last 120 frames): " + this.maxDelta() * 1000 + "ms");
var paragraph = pb.build();
paragraph.layout(new ParagraphConstraints(width: 800));

65
Runtime/ui/painting/utils.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
static class XformUtils {
public static float getAverageScale(Matrix3 matrix) {
return (getScaleX(matrix) + getScaleY(matrix)) * 0.5f;
}
public static float getMaxScale(Matrix3 matrix) {
return Mathf.Max(getScaleX(matrix), getScaleY(matrix));
}
public static float getScaleX(Matrix3 matrix) {
// ignore perspective parameters for now.
if (matrix.isIdentity()) {
return 1.0f;
}
if (matrix.getSkewY() == 0) {
return matrix.getScaleX();
}
var x = matrix.getScaleX();
var y = matrix.getSkewY();
return Mathf.Sqrt(x * x + y * y);
}
public static float getScaleY(Matrix3 matrix) {
// ignore perspective parameters for now.
if (matrix.isIdentity()) {
return 1.0f;
}
if (matrix.getSkewX() == 0) {
return matrix.getScaleY();
}
var x = matrix.getSkewX();
var y = matrix.getScaleY();
return Mathf.Sqrt(x * x + y * y);
}
public static float getScale(Matrix3 matrix) {
var scaleX = getScaleX(matrix);
var scaleY = getScaleY(matrix);
if (scaleX == 1.0) {
return scaleY;
}
if (scaleY == 1.0) {
return scaleX;
}
// geometric mean of len0 and len1.
return Mathf.Sqrt(scaleX * scaleY);
}
public static float mapRadius(Matrix3 matrix, float radius) {
return getScale(matrix) * radius;
}
}
}

11
Runtime/ui/painting/utils.cs.meta


fileFormatVersion: 2
guid: c38089235fcab4985b83cb72b84a9dab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer.meta


fileFormatVersion: 2
guid: 959d5ec4ab46f4b269229c6f3872cb77
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/allocator.meta


fileFormatVersion: 2
guid: 20d8e92bcce4a47289010555ccdb9541
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/allocator/generic_list.cs.meta


fileFormatVersion: 2
guid: eb4160872e9bd4c979becf5c8a3456a4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/allocator/debug.cs.meta


fileFormatVersion: 2
guid: 43af7efe5253d4455b10ffc9e5563b02
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/allocator/pool_object.cs.meta


fileFormatVersion: 2
guid: 10ca9bb0174ca4dc4a01e1b2f2b45f3d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/allocator/uipath_cache_manager.cs.meta


fileFormatVersion: 2
guid: 0bdd45ffa400d4d3d815b21cb97b9d66
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

78
Runtime/ui/renderer/allocator/debug.cs


using System.Collections.Generic;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class DebugMeta {
public string objName;
public int watermark;
public int prev_watermark;
public int borrowed;
public int allocated;
public void onAlloc(int allocatedCount) {
this.borrowed++;
this.watermark = this.borrowed > this.watermark ? this.borrowed : this.watermark;
this.allocated = allocatedCount;
}
public void onRelease(int allocatedCount) {
this.borrowed--;
this.allocated = allocatedCount;
}
}
public static class AllocDebugger {
public const bool enableDebugging = false;
static int allocCount = 0;
static readonly Dictionary<int, DebugMeta> debugInfos = new Dictionary<int, DebugMeta>();
public static void onFrameEnd() {
if (!enableDebugging) {
return;
}
allocCount++;
if (allocCount >= 120) {
allocCount = 0;
string debugInfo = "Alloc Stats: ";
foreach (var key in debugInfos.Keys) {
var item = debugInfos[key];
if (item.watermark <= item.prev_watermark) {
debugInfo += "|" + item.objName + " = " + item.watermark + "," + item.borrowed + "|";
continue;
}
item.prev_watermark = item.watermark;
debugInfo += "|" + item.objName + " = " + item.watermark + "," + item.borrowed + "|";
}
if (debugInfo == "Alloc Stats: ") {
return;
}
Debug.Log(debugInfo);
}
}
public static void onAlloc(int objKey, string objName, int allocatedCount) {
if (!debugInfos.ContainsKey(objKey)) {
debugInfos[objKey] = new DebugMeta {
objName = objName,
watermark = 0,
borrowed = 0,
allocated = 0
};
}
debugInfos[objKey].onAlloc(allocatedCount);
}
public static void onRelease(int objKey, string objName, int allocatedCount) {
Debug.Assert(debugInfos.ContainsKey(objKey), "An unregistered pool object cannot be released");
debugInfos[objKey].onRelease(allocatedCount);
}
}
}

51
Runtime/ui/renderer/allocator/generic_list.cs


using System;
using System.Collections.Generic;
namespace Unity.UIWidgets.ui {
public class uiList<T> : PoolObject {
List<T> list;
public override void setup() {
base.setup();
this.list = this.list ?? new List<T>(128);
}
public uiList() {
}
public List<T> data {
get { return this.list; }
}
public void Add(T item) {
this.list.Add(item);
}
public void AddRange(IList<T> items) {
this.list.AddRange(items);
}
public void Clear() {
this.list.Clear();
}
public override void clear() {
//clear the list immediately to avoid potential memory leak
//otherwise, we may clear it in Setup() for lazy update
this.list.Clear();
}
public int Count {
get { return this.list.Count; }
}
public void SetCapacity(int capacity) {
this.list.Capacity = Math.Max(capacity, this.list.Capacity);
}
public T this[int index] {
get { return this.list[index]; }
set { this.list[index] = value; }
}
}
}

106
Runtime/ui/renderer/allocator/pool_object.cs


using System.Collections.Generic;
using System.Diagnostics;
namespace Unity.UIWidgets.ui {
public abstract class PoolObject {
public bool activated_flag;
public virtual void setup() {
}
public virtual void clear() {
}
}
public static class ObjectPool<TObject> where TObject : PoolObject, new() {
static readonly Stack<TObject> pool = new Stack<TObject>();
const int POOL_MAX_SIZE = 256;
const int POOL_BATCH_SIZE = 128;
static int allocatedCount = 0;
public static TObject alloc() {
if (pool.Count == 0) {
for (int i = 0; i < POOL_BATCH_SIZE; i++) {
var obj = new TObject();
pool.Push(obj);
}
allocatedCount += POOL_BATCH_SIZE;
}
var ret = pool.Pop();
ret.setup();
if (AllocDebugger.enableDebugging) {
AllocDebugger.onAlloc(debugKey, debugName, allocatedCount);
ret.activated_flag = true;
}
return ret;
}
public static void release(TObject obj) {
if (obj == null) {
return;
}
if (AllocDebugger.enableDebugging) {
if (!obj.activated_flag) {
Debug.Assert(false, "an item has been recycled more than once !");
}
obj.activated_flag = false;
AllocDebugger.onRelease(debugKey, debugName, allocatedCount);
}
obj.clear();
if (pool.Count > POOL_MAX_SIZE) {
allocatedCount--;
//there are enough items in the pool
//just release the obj to GC
return;
}
pool.Push(obj);
}
//For debugger
static bool _debugInfoReady = false;
static string _debugName = null;
static void _generateDebugInfo() {
var ctype = typeof(TObject);
_debugName = ctype.ToString();
_debugKey = ctype.GetHashCode();
_debugInfoReady = true;
}
public static string debugName {
get {
if (_debugInfoReady) {
return _debugName;
}
_generateDebugInfo();
return _debugName;
}
}
static int _debugKey = -1;
public static int debugKey {
get {
if (_debugInfoReady) {
return _debugKey;
}
_generateDebugInfo();
return _debugKey;
}
}
}
}

54
Runtime/ui/renderer/allocator/uipath_cache_manager.cs


using System.Collections.Generic;
namespace Unity.UIWidgets.ui {
public static class uiPathCacheManager {
static readonly Dictionary<uint, uiPath> cache = new Dictionary<uint, uiPath>(256);
//remove unused cache items every 1 frame
static readonly Dictionary<uint, bool> touched = new Dictionary<uint, bool>(256);
static float curFrame;
static readonly List<uint> untouched = new List<uint>();
public static void tickNextFrame() {
untouched.Clear();
foreach (var key in cache.Keys) {
if (!touched.ContainsKey(key)) {
untouched.Add(key);
}
}
foreach (var key in untouched) {
ObjectPool<uiPath>.release(cache[key]);
cache.Remove(key);
}
touched.Clear();
}
public static void putToCache(uiPath uipath) {
if (!uipath.needCache) {
ObjectPool<uiPath>.release(uipath);
}
}
public static bool tryGetUiPath(uint pathKey, out uiPath outpath) {
if (cache.ContainsKey(pathKey)) {
touched[pathKey] = true;
outpath = cache[pathKey];
return true;
}
var uipath = uiPath.create();
cache[pathKey] = uipath;
touched[pathKey] = true;
uipath.needCache = true;
uipath.pathKey = pathKey;
outpath = uipath;
return false;
}
}
}

8
Runtime/ui/renderer/cmdbufferCanvas.meta


fileFormatVersion: 2
guid: 59ae365032f57410abbcb34d28138edf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

27
Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public class CommandBufferCanvas : uiRecorderCanvas {
readonly PictureFlusher _flusher;
public CommandBufferCanvas(RenderTexture renderTexture, float devicePixelRatio, MeshPool meshPool)
: base(new uiPictureRecorder()) {
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._flusher.flush(picture);
this._recorder.reset();
ObjectPool<uiPicture>.release(picture);
}
public void dispose() {
this._flusher.dispose();
}
}
}

11
Runtime/ui/renderer/cmdbufferCanvas/command_buffer_canvas.cs.meta


fileFormatVersion: 2
guid: fe2bf6f68e1cf499ab843e5c1d9b8649
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/cmdbufferCanvas/rendering.meta


fileFormatVersion: 2
guid: d6d93fe2039d44a6ca78658b1e59517d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_clip.cs.meta


fileFormatVersion: 2
guid: aeb41cec5a3df49a8bfb3d548f3ad93d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

1001
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs
文件差异内容过多而无法显示
查看文件

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_impl.cs.meta


fileFormatVersion: 2
guid: 4819b50eb486840f29658385ccd9d198
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader.cs.meta


fileFormatVersion: 2
guid: 7c11a48c082af4e16a8ec27bed8aafbe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

39
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public class MaterialPropertyBlockWrapper : PoolObject {
public readonly MaterialPropertyBlock mpb;
public MaterialPropertyBlockWrapper() {
this.mpb = new MaterialPropertyBlock();
}
public override void clear() {
this.mpb.Clear();
}
public void SetVector(int mid, Vector4 vec) {
this.mpb.SetVector(mid, vec);
}
public void SetFloat(int mid, float value) {
this.mpb.SetFloat(mid, value);
}
public void SetMatrix(int mid, Matrix4x4 mat) {
this.mpb.SetMatrix(mid, mat);
}
public void SetTexture(int mid, Texture texture) {
this.mpb.SetTexture(mid, texture);
}
public void SetInt(int mid, int value) {
this.mpb.SetInt(mid, value);
}
public void SetFloatArray(int mid, float[] array) {
this.mpb.SetFloatArray(mid, array);
}
}
}

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_shader_utils.cs.meta


fileFormatVersion: 2
guid: e765af15bd449426d96889c83da3f18f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

232
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
static class BlurUtils {
static readonly Dictionary<int, float[]> _gaussianKernels
= new Dictionary<int, float[]>();
static float[] calculateKernel(float _cur_gaussian_sigma, int _cur_width, int _cur_radius) {
var kernel = new float[25];
float twoSigmaSqrd = 2.0f * _cur_gaussian_sigma * _cur_gaussian_sigma;
if (ScalarUtils.ScalarNearlyZero(twoSigmaSqrd)) {
for (int i = 0; i < _cur_width; ++i) {
kernel[i] = 0.0f;
}
return kernel;
}
float denom = 1.0f / twoSigmaSqrd;
float sum = 0.0f;
for (int i = 0; i < _cur_width; ++i) {
float x = i - _cur_radius;
// Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
// is dropped here, since we renormalize the kernel below.
kernel[i] = Mathf.Exp(-x * x * denom);
sum += kernel[i];
}
// Normalize the kernel
float scale = 1.0f / sum;
for (int i = 0; i < _cur_width; ++i) {
kernel[i] *= scale;
}
_cur_gaussian_sigma = -1;
_cur_radius = -1;
return kernel;
}
public static float[] get1DGaussianKernel(float gaussianSigma, int radius) {
var width = 2 * radius + 1;
D.assert(width <= 25);
//round gaussian sigma to 0.1
gaussianSigma = Mathf.Round(gaussianSigma * 10) / 10f;
//assume radius < 10000
D.assert(radius < 10000);
int key = (int) (gaussianSigma * 1000000) + radius;
float[] value;
if (_gaussianKernels.TryGetValue(key, out value)) {
return value;
}
value = calculateKernel(gaussianSigma, width, radius);
_gaussianKernels[key] = value;
return value;
}
public static float adjustSigma(float sigma, out int scaleFactor, out int radius) {
scaleFactor = 1;
const int maxTextureSize = 16384;
const float MAX_BLUR_SIGMA = 4.0f;
while (sigma > MAX_BLUR_SIGMA) {
scaleFactor *= 2;
sigma *= 0.5f;
if (scaleFactor > maxTextureSize) {
scaleFactor = maxTextureSize;
sigma = MAX_BLUR_SIGMA;
}
}
radius = Mathf.CeilToInt(sigma * 3.0f);
D.assert(radius <= 3 * MAX_BLUR_SIGMA);
return sigma;
}
}
static class ImageMeshGenerator {
static readonly List<int> _imageTriangles = new List<int>(12) {
0, 1, 2, 0, 2, 1,
0, 2, 3, 0, 3, 2,
};
static readonly List<int> _imageNineTriangles = new List<int> {
0, 4, 1, 1, 4, 5,
0, 1, 4, 1, 5, 4,
1, 5, 2, 2, 5, 6,
1, 2, 5, 2, 6, 5,
2, 6, 3, 3, 6, 7,
2, 3, 6, 3, 7, 6,
4, 8, 5, 5, 8, 9,
4, 5, 8, 5, 9, 8,
5, 9, 6, 6, 9, 10,
5, 6, 9, 6, 10, 9,
6, 10, 7, 7, 10, 11,
6, 7, 10, 7, 11, 10,
8, 12, 9, 9, 12, 13,
8, 9, 12, 9, 13, 12,
9, 13, 10, 10, 13, 14,
9, 10, 13, 10, 14, 13,
10, 14, 11, 11, 14, 15,
10, 11, 14, 11, 15, 14,
};
public static uiMeshMesh imageMesh(uiMatrix3? matrix,
uiOffset srcTL, uiOffset srcBL, uiOffset srcBR, uiOffset srcTR,
uiRect dst) {
var vertices = ObjectPool<uiList<Vector3>>.alloc();
vertices.SetCapacity(4);
var uv = ObjectPool<uiList<Vector2>>.alloc();
uv.SetCapacity(4);
vertices.Add(new Vector2(dst.left, dst.top));
uv.Add(new Vector2(srcTL.dx, 1.0f - srcTL.dy));
vertices.Add(new Vector2(dst.left, dst.bottom));
uv.Add(new Vector2(srcBL.dx, 1.0f - srcBL.dy));
vertices.Add(new Vector2(dst.right, dst.bottom));
uv.Add(new Vector2(srcBR.dx, 1.0f - srcBR.dy));
vertices.Add(new Vector2(dst.right, dst.top));
uv.Add(new Vector2(srcTR.dx, 1.0f - srcTR.dy));
var _triangles = ObjectPool<uiList<int>>.alloc();
_triangles.AddRange(_imageTriangles);
return uiMeshMesh.create(matrix, vertices, _triangles, uv);
}
public static uiMeshMesh imageMesh(uiMatrix3? matrix, uiRect src, uiRect dst) {
var vertices = ObjectPool<uiList<Vector3>>.alloc();
vertices.SetCapacity(4);
var uv = ObjectPool<uiList<Vector2>>.alloc();
uv.SetCapacity(4);
float uvx0 = src.left;
float uvx1 = src.right;
float uvy0 = 1.0f - src.top;
float uvy1 = 1.0f - src.bottom;
vertices.Add(new Vector2(dst.left, dst.top));
uv.Add(new Vector2(uvx0, uvy0));
vertices.Add(new Vector2(dst.left, dst.bottom));
uv.Add(new Vector2(uvx0, uvy1));
vertices.Add(new Vector2(dst.right, dst.bottom));
uv.Add(new Vector2(uvx1, uvy1));
vertices.Add(new Vector2(dst.right, dst.top));
uv.Add(new Vector2(uvx1, uvy0));
var _triangles = ObjectPool<uiList<int>>.alloc();
_triangles.AddRange(_imageTriangles);
return uiMeshMesh.create(matrix, vertices, _triangles, uv);
}
public static uiMeshMesh imageNineMesh(uiMatrix3? matrix, uiRect src, uiRect center, int srcWidth,
int srcHeight, uiRect dst) {
float x0 = dst.left;
float x3 = dst.right;
float x1 = x0 + ((center.left - src.left) * srcWidth);
float x2 = x3 - ((src.right - center.right) * srcWidth);
float y0 = dst.top;
float y3 = dst.bottom;
float y1 = y0 + ((center.top - src.top) * srcHeight);
float y2 = y3 - ((src.bottom - center.bottom) * srcHeight);
float tx0 = src.left;
float tx1 = center.left;
float tx2 = center.right;
float tx3 = src.right;
float ty0 = 1 - src.top;
float ty1 = 1 - center.top;
float ty2 = 1 - center.bottom;
float ty3 = 1 - src.bottom;
var vertices = ObjectPool<uiList<Vector3>>.alloc();
vertices.SetCapacity(16);
var uv = ObjectPool<uiList<Vector2>>.alloc();
uv.SetCapacity(16);
vertices.Add(new Vector2(x0, y0));
uv.Add(new Vector2(tx0, ty0));
vertices.Add(new Vector2(x1, y0));
uv.Add(new Vector2(tx1, ty0));
vertices.Add(new Vector2(x2, y0));
uv.Add(new Vector2(tx2, ty0));
vertices.Add(new Vector2(x3, y0));
uv.Add(new Vector2(tx3, ty0));
vertices.Add(new Vector2(x0, y1));
uv.Add(new Vector2(tx0, ty1));
vertices.Add(new Vector2(x1, y1));
uv.Add(new Vector2(tx1, ty1));
vertices.Add(new Vector2(x2, y1));
uv.Add(new Vector2(tx2, ty1));
vertices.Add(new Vector2(x3, y1));
uv.Add(new Vector2(tx3, ty1));
vertices.Add(new Vector2(x0, y2));
uv.Add(new Vector2(tx0, ty2));
vertices.Add(new Vector2(x1, y2));
uv.Add(new Vector2(tx1, ty2));
vertices.Add(new Vector2(x2, y2));
uv.Add(new Vector2(tx2, ty2));
vertices.Add(new Vector2(x3, y2));
uv.Add(new Vector2(tx3, ty2));
vertices.Add(new Vector2(x0, y3));
uv.Add(new Vector2(tx0, ty3));
vertices.Add(new Vector2(x1, y3));
uv.Add(new Vector2(tx1, ty3));
vertices.Add(new Vector2(x2, y3));
uv.Add(new Vector2(tx2, ty3));
vertices.Add(new Vector2(x3, y3));
uv.Add(new Vector2(tx3, ty3));
var _triangles = ObjectPool<uiList<int>>.alloc();
_triangles.AddRange(_imageNineTriangles);
return uiMeshMesh.create(matrix, vertices, _triangles, uv);
}
}
}

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/canvas_utils.cs.meta


fileFormatVersion: 2
guid: 039549b55460f4773b43ddae683ddcd4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

100
Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public partial class PictureFlusher {
internal abstract class RenderCmd : PoolObject {
public abstract void release();
}
internal class CmdLayer : RenderCmd {
public RenderLayer layer;
public CmdLayer() {
}
public override void clear() {
this.layer = null;
}
public static CmdLayer create(RenderLayer layer) {
CmdLayer newCmd = ObjectPool<CmdLayer>.alloc();
newCmd.layer = layer;
return newCmd;
}
public override void release() {
ObjectPool<CmdLayer>.release(this);
}
}
internal class CmdDraw : RenderCmd {
public uiMeshMesh mesh;
public TextBlobMesh textMesh;
public int pass;
public MaterialPropertyBlockWrapper properties;
public int? layerId;
public Material material;
public Image image; // just to keep a reference to avoid GC.
public Mesh meshObj;
public bool meshObjCreated;
public static readonly Matrix4x4 idMat = Matrix4x4.identity;
public static readonly Matrix3 idMat3 = Matrix3.I();
public static readonly int texId = Shader.PropertyToID("_tex");
public static readonly int matId = Shader.PropertyToID("_mat");
public override void clear() {
ObjectPool<uiMeshMesh>.release(this.mesh);
ObjectPool<TextBlobMesh>.release(this.textMesh);
ObjectPool<MaterialPropertyBlockWrapper>.release(this.properties);
}
public CmdDraw() {
}
public static CmdDraw create(uiMeshMesh mesh = null, TextBlobMesh textMesh = null, int pass = 0,
MaterialPropertyBlockWrapper properties = null, int? layerId = null, Material material = null,
Image image = null, Mesh meshObj = null,
bool meshObjCreated = false) {
CmdDraw newCmd = ObjectPool<CmdDraw>.alloc();
newCmd.mesh = mesh;
newCmd.textMesh = textMesh;
newCmd.pass = pass;
newCmd.properties = properties;
newCmd.layerId = layerId;
newCmd.material = material;
newCmd.image = image;
newCmd.meshObj = meshObj;
newCmd.meshObjCreated = meshObjCreated;
return newCmd;
}
public override void release() {
ObjectPool<CmdDraw>.release(this);
}
}
internal class CmdScissor : RenderCmd {
public uiRect? deviceScissor;
public CmdScissor() {
}
public override void clear() {
this.deviceScissor = null;
}
public static CmdScissor create(uiRect? deviceScissor) {
CmdScissor newCmd = ObjectPool<CmdScissor>.alloc();
newCmd.deviceScissor = deviceScissor;
return newCmd;
}
public override void release() {
ObjectPool<CmdScissor>.release(this);
}
}
}
}

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/render_cmd.cs.meta


fileFormatVersion: 2
guid: cbfd23f193e6d4e9b86c08ac62694399
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

141
Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public partial class PictureFlusher {
internal class RenderLayer : PoolObject {
public int rtID;
public int width;
public int height;
public FilterMode filterMode = FilterMode.Bilinear;
public bool noMSAA = false;
public uiRect layerBounds;
public uiPaint? layerPaint;
public readonly List<RenderCmd> draws = new List<RenderCmd>(128);
public readonly List<RenderLayer> layers = new List<RenderLayer>(16);
public readonly List<State> states = new List<State>(16);
public State currentState;
public ClipStack clipStack;
public uint lastClipGenId;
public uiRect lastClipBounds;
public bool ignoreClip = true;
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 static RenderLayer create(int rtID = 0, int width = 0, int height = 0,
FilterMode filterMode = FilterMode.Bilinear,
bool noMSAA = false, uiRect? layerBounds = null, uiPaint? layerPaint = null, bool ignoreClip = true) {
D.assert(layerBounds != null);
var newLayer = ObjectPool<RenderLayer>.alloc();
newLayer.rtID = rtID;
newLayer.width = width;
newLayer.height = height;
newLayer.filterMode = filterMode;
newLayer.noMSAA = noMSAA;
newLayer.layerBounds = layerBounds.Value;
newLayer.layerPaint = layerPaint;
newLayer.ignoreClip = ignoreClip;
newLayer.currentState = State.create();
newLayer.states.Add(newLayer.currentState);
newLayer.clipStack = ClipStack.create();
return newLayer;
}
public void addLayer(RenderLayer layer) {
this.layers.Add(layer);
this.draws.Add(CmdLayer.create(layer: layer));
}
public override void clear() {
//these two list should have been cleared in PictureFlusher._clearLayer
D.assert(this.draws.Count == 0);
D.assert(this.layers.Count == 0);
this.draws.Clear();
this.layers.Clear();
foreach (var state in this.states) {
ObjectPool<State>.release(state);
}
this.states.Clear();
ObjectPool<ClipStack>.release(this.clipStack);
this._viewport = null;
}
}
internal class State : PoolObject {
public State() {
}
static readonly uiMatrix3 _id = uiMatrix3.I();
uiMatrix3? _matrix;
float? _scale;
uiMatrix3? _invMatrix;
public static State create(uiMatrix3? matrix = null, float? scale = null, uiMatrix3? invMatrix = null) {
State newState = ObjectPool<State>.alloc();
newState._matrix = matrix ?? _id;
newState._scale = scale;
newState._invMatrix = invMatrix;
return newState;
}
public override void clear() {
this._matrix = null;
this._scale = null;
this._invMatrix = null;
}
public uiMatrix3? matrix {
get { return this._matrix; }
set {
this._matrix = value ?? _id;
this._scale = null;
this._invMatrix = null;
}
}
public float scale {
get {
if (this._scale == null) {
this._scale = uiXformUtils.getScale(this._matrix.Value);
}
return this._scale.Value;
}
}
public uiMatrix3 invMatrix {
get {
if (this._invMatrix == null) {
this._invMatrix = this._matrix.Value.invert();
}
return this._invMatrix.Value;
}
}
public State copy() {
return create(this._matrix, this._scale, this._invMatrix);
}
}
}
}

11
Runtime/ui/renderer/cmdbufferCanvas/rendering/render_layer.cs.meta


fileFormatVersion: 2
guid: 80db86b2e84084672a0573836aa60f64
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/common.meta


fileFormatVersion: 2
guid: 0f5bbea100d7f4b26b7353f0732299d5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

308
Runtime/ui/renderer/common/base_canvas.cs


using System;
using Unity.UIWidgets.flow;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public class uiRecorderCanvas : Canvas {
public uiRecorderCanvas(uiPictureRecorder recorder) {
this._recorder = recorder;
}
protected readonly uiPictureRecorder _recorder;
int _saveCount = 1;
public void save() {
this._saveCount++;
this._recorder.addDrawCmd(uiDrawSave.create());
}
public void saveLayer(Rect rect, Paint paint) {
this._saveCount++;
this._recorder.addDrawCmd(uiDrawSaveLayer.create(
rect: uiRectHelper.fromRect(rect),
paint: uiPaint.fromPaint(paint)
));
}
public void restore() {
this._saveCount--;
this._recorder.addDrawCmd(uiDrawRestore.create());
}
public int getSaveCount() {
return this._saveCount;
}
public void translate(float dx, float dy) {
this._recorder.addDrawCmd(uiDrawTranslate.create(
dx: dx,
dy: dy
));
}
public void scale(float sx, float? sy = null) {
this._recorder.addDrawCmd(uiDrawScale.create(
sx: sx,
sy: sy
));
}
public void rotate(float radians, Offset offset = null) {
this._recorder.addDrawCmd(uiDrawRotate.create(
radians: radians,
offset: uiOffset.fromOffset(offset)
));
}
public void skew(float sx, float sy) {
this._recorder.addDrawCmd(uiDrawSkew.create(
sx: sx,
sy: sy
));
}
public void concat(Matrix3 matrix) {
this._recorder.addDrawCmd(uiDrawConcat.create(
matrix: uiMatrix3.fromMatrix3(matrix)
));
}
readonly Matrix3 _totalMatrix = Matrix3.I();
public Matrix3 getTotalMatrix() {
var localMatrix = this._recorder.getTotalMatrix();
this._totalMatrix.setAll(localMatrix.kMScaleX, localMatrix.kMSkewX, localMatrix.kMTransX,
localMatrix.kMSkewY, localMatrix.kMScaleY, localMatrix.kMTransY,
localMatrix.kMPersp0, localMatrix.kMPersp1, localMatrix.kMPersp2);
return this._totalMatrix;
}
public void resetMatrix() {
this._recorder.addDrawCmd(uiDrawResetMatrix.create(
));
}
public void setMatrix(Matrix3 matrix) {
this._recorder.addDrawCmd(uiDrawSetMatrix.create(
matrix: uiMatrix3.fromMatrix3(matrix)
));
}
public virtual float getDevicePixelRatio() {
throw new Exception("not available in recorder");
}
public void clipRect(Rect rect) {
this._recorder.addDrawCmd(uiDrawClipRect.create(
rect: uiRectHelper.fromRect(rect)
));
}
public void clipRRect(RRect rrect) {
this._recorder.addDrawCmd(uiDrawClipRRect.create(
rrect: rrect
));
}
public void clipPath(Path path) {
this._recorder.addDrawCmd(uiDrawClipPath.create(
path: uiPath.fromPath(path)
));
}
public void drawLine(Offset from, Offset to, Paint paint) {
var path = uiPath.create();
path.moveTo(from.dx, from.dy);
path.lineTo(to.dx, to.dy);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawShadow(Path path, Color color, float elevation, bool transparentOccluder) {
float dpr = Window.instance.devicePixelRatio;
PhysicalShapeLayer.drawShadow(this, path, color, elevation, transparentOccluder, dpr);
}
public void drawRect(Rect rect, Paint paint) {
if (rect.size.isEmpty) {
return;
}
var path = uiPath.create();
path.addRect(rect);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawRRect(RRect rrect, Paint paint) {
var path = uiPath.create();
path.addRRect(rrect);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawDRRect(RRect outer, RRect inner, Paint paint) {
var path = uiPath.create();
path.addRRect(outer);
path.addRRect(inner);
path.winding(PathWinding.clockwise);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawOval(Rect rect, Paint paint) {
var w = rect.width / 2;
var h = rect.height / 2;
var path = uiPath.create();
path.addEllipse(rect.left + w, rect.top + h, w, h);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawCircle(Offset c, float radius, Paint paint) {
var path = uiPath.create();
path.addCircle(c.dx, c.dy, radius);
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawArc(Rect rect, float startAngle, float sweepAngle, bool useCenter, Paint paint) {
var path = uiPath.create();
if (useCenter) {
var center = rect.center;
path.moveTo(center.dx, center.dy);
}
bool forceMoveTo = !useCenter;
while (sweepAngle <= -Mathf.PI * 2) {
path.arcTo(rect, startAngle, -Mathf.PI, forceMoveTo);
startAngle -= Mathf.PI;
path.arcTo(rect, startAngle, -Mathf.PI, false);
startAngle -= Mathf.PI;
forceMoveTo = false;
sweepAngle += Mathf.PI * 2;
}
while (sweepAngle >= Mathf.PI * 2) {
path.arcTo(rect, startAngle, Mathf.PI, forceMoveTo);
startAngle += Mathf.PI;
path.arcTo(rect, startAngle, Mathf.PI, false);
startAngle += Mathf.PI;
forceMoveTo = false;
sweepAngle -= Mathf.PI * 2;
}
path.arcTo(rect, startAngle, sweepAngle, forceMoveTo);
if (useCenter) {
path.close();
}
this._recorder.addDrawCmd(uiDrawPath.create(
path: path,
paint: uiPaint.fromPaint(paint)
));
}
public void drawPath(Path path, Paint paint) {
this._recorder.addDrawCmd(uiDrawPath.create(
path: uiPath.fromPath(path),
paint: uiPaint.fromPaint(paint)
));
}
public void drawImage(Image image, Offset offset, Paint paint) {
this._recorder.addDrawCmd(uiDrawImage.create(
image: image,
offset: uiOffset.fromOffset(offset),
paint: uiPaint.fromPaint(paint)
));
}
public void drawImageRect(Image image, Rect dst, Paint paint) {
this._recorder.addDrawCmd(uiDrawImageRect.create(
image: image,
src: null,
dst: uiRectHelper.fromRect(dst),
paint: uiPaint.fromPaint(paint)
));
}
public void drawImageRect(Image image, Rect src, Rect dst, Paint paint) {
this._recorder.addDrawCmd(uiDrawImageRect.create(
image: image,
src: uiRectHelper.fromRect(src),
dst: uiRectHelper.fromRect(dst),
paint: uiPaint.fromPaint(paint)
));
}
public void drawImageNine(Image image, Rect center, Rect dst, Paint paint) {
this._recorder.addDrawCmd(uiDrawImageNine.create(
image: image,
src: null,
center: uiRectHelper.fromRect(center),
dst: uiRectHelper.fromRect(dst),
paint: uiPaint.fromPaint(paint)
));
}
public void drawImageNine(Image image, Rect src, Rect center, Rect dst, Paint paint) {
this._recorder.addDrawCmd(uiDrawImageNine.create(
image: image,
src: uiRectHelper.fromRect(src),
center: uiRectHelper.fromRect(center),
dst: uiRectHelper.fromRect(dst),
paint: uiPaint.fromPaint(paint)
));
}
public void drawPicture(Picture picture) {
this._recorder.addDrawCmd(uiDrawPicture.create(
picture: picture
));
}
public void drawTextBlob(TextBlob textBlob, Offset offset, Paint paint) {
this._recorder.addDrawCmd(uiDrawTextBlob.create(
textBlob: textBlob,
offset: uiOffset.fromOffset(offset),
paint: uiPaint.fromPaint(paint)
));
}
public void drawParagraph(Paragraph paragraph, Offset offset) {
D.assert(paragraph != null);
D.assert(PaintingUtils._offsetIsValid(offset));
paragraph.paint(this, offset);
}
public virtual void flush() {
throw new Exception("not available in recorder");
}
public void reset() {
this._recorder.reset();
}
}
}

11
Runtime/ui/renderer/common/base_canvas.cs.meta


fileFormatVersion: 2
guid: 1859b421a4bfc49c68c7ff6ed3991449
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

80
Runtime/ui/renderer/common/color.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public struct uiColor {
public readonly long value;
public uiColor(long value) {
this.value = value & 0xFFFFFFFF;
}
public static readonly uiColor clear = new uiColor(0x00000000);
public static readonly uiColor black = new uiColor(0xFF000000);
public static readonly uiColor white = new uiColor(0xFFFFFFFF);
public int alpha {
get { return (int) ((0xff000000 & this.value) >> 24); }
}
public float opacity {
get { return this.alpha / 255.0f; }
}
public int red {
get { return (int) ((0x00ff0000 & this.value) >> 16); }
}
public int green {
get { return (int) ((0x0000ff00 & this.value) >> 8); }
}
public int blue {
get { return (int) ((0x000000ff & this.value) >> 0); }
}
public static uiColor fromColor(Color color) {
return new uiColor(color.value);
}
public static uiColor fromARGB(int a, int r, int g, int b) {
return new uiColor(
(((a & 0xff) << 24) |
((r & 0xff) << 16) |
((g & 0xff) << 8) |
((b & 0xff) << 0)) & 0xFFFFFFFF);
}
public static uiColor fromRGBO(int r, int g, int b, float opacity) {
return new uiColor(
((((int) (opacity * 0xff) & 0xff) << 24) |
((r & 0xff) << 16) |
((g & 0xff) << 8) |
((b & 0xff) << 0)) & 0xFFFFFFFF);
}
public uiColor withAlpha(int a) {
return fromARGB(a, this.red, this.green, this.blue);
}
public uiColor withOpacity(float opacity) {
return this.withAlpha((int) (opacity * 255));
}
static float _linearizeColorComponent(float component) {
if (component <= 0.03928f) {
return component / 12.92f;
}
return Mathf.Pow((component + 0.055f) / 1.055f, 2.4f);
}
public float computeLuminance() {
float R = _linearizeColorComponent(this.red / 0xFF);
float G = _linearizeColorComponent(this.green / 0xFF);
float B = _linearizeColorComponent(this.blue / 0xFF);
return 0.2126f * R + 0.7152f * G + 0.0722f * B;
}
}
}

11
Runtime/ui/renderer/common/color.cs.meta


fileFormatVersion: 2
guid: 461310626ee954e13b72c5e70bd4a5f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

415
Runtime/ui/renderer/common/draw_cmd.cs


namespace Unity.UIWidgets.ui {
public abstract class uiDrawCmd : PoolObject {
public abstract void release();
}
public class uiDrawSave : uiDrawCmd {
public uiDrawSave() {
}
public static uiDrawSave create() {
var drawSave = ObjectPool<uiDrawSave>.alloc();
return drawSave;
}
public override void release() {
ObjectPool<uiDrawSave>.release(this);
}
}
public class uiDrawSaveLayer : uiDrawCmd {
public uiDrawSaveLayer() {
}
public static uiDrawSaveLayer create(uiRect? rect, uiPaint paint) {
var drawSaveLayer = ObjectPool<uiDrawSaveLayer>.alloc();
drawSaveLayer.rect = rect;
drawSaveLayer.paint = paint;
return drawSaveLayer;
}
public override void release() {
ObjectPool<uiDrawSaveLayer>.release(this);
}
public override void clear() {
this.rect = null;
}
public uiRect? rect;
public uiPaint paint;
}
public class uiDrawRestore : uiDrawCmd {
public uiDrawRestore() {
}
public static uiDrawRestore create() {
var drawRestore = ObjectPool<uiDrawRestore>.alloc();
return drawRestore;
}
public override void release() {
ObjectPool<uiDrawRestore>.release(this);
}
}
public class uiDrawTranslate : uiDrawCmd {
public uiDrawTranslate() {
}
public static uiDrawTranslate create(float dx, float dy) {
var drawTranslate = ObjectPool<uiDrawTranslate>.alloc();
drawTranslate.dx = dx;
drawTranslate.dy = dy;
return drawTranslate;
}
public override void release() {
ObjectPool<uiDrawTranslate>.release(this);
}
public float dx;
public float dy;
}
public class uiDrawScale : uiDrawCmd {
public uiDrawScale() {
}
public static uiDrawScale create(float sx, float? sy) {
var drawScale = ObjectPool<uiDrawScale>.alloc();
drawScale.sx = sx;
drawScale.sy = sy;
return drawScale;
}
public override void release() {
ObjectPool<uiDrawScale>.release(this);
}
public float sx;
public float? sy;
}
public class uiDrawRotate : uiDrawCmd {
public uiDrawRotate() {
}
public static uiDrawRotate create(float radians, uiOffset? offset) {
var drawRotate = ObjectPool<uiDrawRotate>.alloc();
drawRotate.radians = radians;
drawRotate.offset = offset;
return drawRotate;
}
public override void release() {
ObjectPool<uiDrawRotate>.release(this);
}
public override void clear() {
this.offset = null;
}
public float radians;
public uiOffset? offset;
}
public class uiDrawSkew : uiDrawCmd {
public uiDrawSkew() {
}
public static uiDrawSkew create(float sx, float sy) {
var drawSkew = ObjectPool<uiDrawSkew>.alloc();
drawSkew.sx = sx;
drawSkew.sy = sy;
return drawSkew;
}
public override void release() {
ObjectPool<uiDrawSkew>.release(this);
}
public float sx;
public float sy;
}
public class uiDrawConcat : uiDrawCmd {
public uiDrawConcat() {
}
public static uiDrawConcat create(uiMatrix3? matrix) {
var drawConcat = ObjectPool<uiDrawConcat>.alloc();
drawConcat.matrix = matrix;
return drawConcat;
}
public override void release() {
ObjectPool<uiDrawConcat>.release(this);
}
public override void clear() {
this.matrix = null;
}
public uiMatrix3? matrix;
}
public class uiDrawResetMatrix : uiDrawCmd {
public uiDrawResetMatrix() {
}
public static uiDrawResetMatrix create() {
var drawResetMatrix = ObjectPool<uiDrawResetMatrix>.alloc();
return drawResetMatrix;
}
public override void release() {
ObjectPool<uiDrawResetMatrix>.release(this);
}
}
public class uiDrawSetMatrix : uiDrawCmd {
public uiDrawSetMatrix() {
}
public static uiDrawSetMatrix create(uiMatrix3? matrix) {
var drawSetMatrix = ObjectPool<uiDrawSetMatrix>.alloc();
drawSetMatrix.matrix = matrix;
return drawSetMatrix;
}
public override void release() {
ObjectPool<uiDrawSetMatrix>.release(this);
}
public override void clear() {
this.matrix = null;
}
public uiMatrix3? matrix;
}
public class uiDrawClipRect : uiDrawCmd {
public uiDrawClipRect() {
}
public static uiDrawClipRect create(uiRect? rect) {
var drawClipRect = ObjectPool<uiDrawClipRect>.alloc();
drawClipRect.rect = rect;
return drawClipRect;
}
public override void release() {
ObjectPool<uiDrawClipRect>.release(this);
}
public override void clear() {
this.rect = null;
}
public uiRect? rect;
}
public class uiDrawClipRRect : uiDrawCmd {
public uiDrawClipRRect() {
}
public static uiDrawClipRRect create(RRect rrect) {
var drawClipRRect = ObjectPool<uiDrawClipRRect>.alloc();
drawClipRRect.rrect = rrect;
return drawClipRRect;
}
public override void release() {
ObjectPool<uiDrawClipRRect>.release(this);
}
public override void clear() {
this.rrect = null;
}
public RRect rrect;
}
public class uiDrawClipPath : uiDrawCmd {
public uiDrawClipPath() {
}
public static uiDrawClipPath create(uiPath path) {
var drawClipPath = ObjectPool<uiDrawClipPath>.alloc();
drawClipPath.path = path;
return drawClipPath;
}
public override void release() {
ObjectPool<uiDrawClipPath>.release(this);
}
public override void clear() {
//ObjectPool<uiPath>.release(this.path);
uiPathCacheManager.putToCache(this.path);
this.path = null;
}
public uiPath path;
}
public class uiDrawPath : uiDrawCmd {
public uiDrawPath() {
}
public static uiDrawPath create(uiPath path, uiPaint paint) {
var drawPath = ObjectPool<uiDrawPath>.alloc();
drawPath.path = path;
drawPath.paint = paint;
return drawPath;
}
public override void release() {
ObjectPool<uiDrawPath>.release(this);
}
public override void clear() {
//ObjectPool<uiPath>.release(this.path);
uiPathCacheManager.putToCache(this.path);
this.path = null;
}
public uiPath path;
public uiPaint paint;
}
public class uiDrawImage : uiDrawCmd {
public uiDrawImage() {
}
public static uiDrawImage create(Image image, uiOffset? offset, uiPaint paint) {
var drawImage = ObjectPool<uiDrawImage>.alloc();
drawImage.image = image;
drawImage.offset = offset;
drawImage.paint = paint;
return drawImage;
}
public override void release() {
ObjectPool<uiDrawImage>.release(this);
}
public override void clear() {
this.image = null;
this.offset = null;
}
public Image image;
public uiOffset? offset;
public uiPaint paint;
}
public class uiDrawImageRect : uiDrawCmd {
public uiDrawImageRect() {
}
public static uiDrawImageRect create(Image image, uiRect? src, uiRect? dst, uiPaint paint) {
var drawImageRect = ObjectPool<uiDrawImageRect>.alloc();
drawImageRect.image = image;
drawImageRect.src = src;
drawImageRect.dst = dst;
drawImageRect.paint = paint;
return drawImageRect;
}
public override void release() {
ObjectPool<uiDrawImageRect>.release(this);
}
public override void clear() {
this.image = null;
this.src = null;
this.dst = null;
}
public Image image;
public uiRect? src;
public uiRect? dst;
public uiPaint paint;
}
public class uiDrawImageNine : uiDrawCmd {
public uiDrawImageNine() {
}
public static uiDrawImageNine create(Image image, uiRect? src, uiRect? center, uiRect? dst, uiPaint paint) {
var drawImageNine = ObjectPool<uiDrawImageNine>.alloc();
drawImageNine.image = image;
drawImageNine.src = src;
drawImageNine.center = center;
drawImageNine.dst = dst;
drawImageNine.paint = paint;
return drawImageNine;
}
public override void release() {
ObjectPool<uiDrawImageNine>.release(this);
}
public override void clear() {
this.image = null;
this.src = null;
this.center = null;
this.dst = null;
}
public Image image;
public uiRect? src;
public uiRect? center;
public uiRect? dst;
public uiPaint paint;
}
public class uiDrawPicture : uiDrawCmd {
public uiDrawPicture() {
}
public static uiDrawPicture create(Picture picture) {
var drawPicture = ObjectPool<uiDrawPicture>.alloc();
drawPicture.picture = picture;
return drawPicture;
}
public override void release() {
ObjectPool<uiDrawPicture>.release(this);
}
public override void clear() {
this.picture = null;
}
public Picture picture;
}
public class uiDrawTextBlob : uiDrawCmd {
public uiDrawTextBlob() {
}
public static uiDrawTextBlob create(TextBlob textBlob, uiOffset? offset, uiPaint paint) {
var drawTextBlob = ObjectPool<uiDrawTextBlob>.alloc();
drawTextBlob.textBlob = textBlob;
drawTextBlob.offset = offset;
drawTextBlob.paint = paint;
return drawTextBlob;
}
public override void release() {
ObjectPool<uiDrawTextBlob>.release(this);
}
public override void clear() {
this.offset = null;
}
public TextBlob textBlob;
public uiOffset? offset;
public uiPaint paint;
}
}

11
Runtime/ui/renderer/common/draw_cmd.cs.meta


fileFormatVersion: 2
guid: 8b8f342529f264553a2f806b2cad7f32
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/common/geometry.meta


fileFormatVersion: 2
guid: 15f29cc8a09164aefb85d8ee18c69ae1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/offset.cs.meta


fileFormatVersion: 2
guid: 4820cc4e3dc2441c8acd09d43ce23e6c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/rect.cs.meta


fileFormatVersion: 2
guid: cb02ebe9630a944dcbdfb1e1956ea953
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/common/geometry/matrix.meta


fileFormatVersion: 2
guid: 8bd926580ace74793972a8fe7cb93142
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/mesh_mesh.cs.meta


fileFormatVersion: 2
guid: 5c914278a0e574134bd4550922dfd987
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/common/geometry/path.meta


fileFormatVersion: 2
guid: 9833be88343a54d84b02087b3006b98a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs.meta


fileFormatVersion: 2
guid: f7f9e498efb264ed5b85441a492d89f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs.meta


fileFormatVersion: 2
guid: 9d073f36f6673429ab90abc8c3c469a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

761
Runtime/ui/renderer/common/geometry/matrix/ui_matrix.cs


using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public partial struct uiMatrix3 {
//Constants
enum TypeMask {
kIdentity_Mask = 0, //!< identity SkMatrix; all bits clear
kTranslate_Mask = 0x01, //!< translation SkMatrix
kScale_Mask = 0x02, //!< scale SkMatrix
kAffine_Mask = 0x04, //!< skew or rotate SkMatrix
kPerspective_Mask = 0x08, //!< perspective SkMatrix
}
const int kRectStaysRect_Mask = 0x10;
const int kOnlyPerspectiveValid_Mask = 0x40;
const int kUnknown_Mask = 0x80;
const int kORableMasks =
(int)
(TypeMask.kTranslate_Mask |
TypeMask.kScale_Mask |
TypeMask.kAffine_Mask |
TypeMask.kPerspective_Mask);
const int kAllMasks =
(int)
(TypeMask.kTranslate_Mask |
TypeMask.kScale_Mask |
TypeMask.kAffine_Mask |
TypeMask.kPerspective_Mask) |
kRectStaysRect_Mask;
enum TypeShift {
kTranslate_Shift,
kScale_Shift,
kAffine_Shift,
kPerspective_Shift,
kRectStaysRect_Shift
}
const int kScalar1Int = 0x3f800000;
}
public partial struct uiMatrix3 {
//Variables
public float kMScaleX; //0
public float kMSkewX; //1
public float kMTransX; //2
public float kMSkewY; //3
public float kMScaleY; //4
public float kMTransY; //5
public float kMPersp0; //6
public float kMPersp1; //7
public float kMPersp2; //8
public int fTypeMask;
}
public partial struct uiMatrix3 {
//private methods
void _setScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
this.reset();
}
else {
this.kMScaleX = sx;
this.kMScaleY = sy;
this.kMPersp2 = 1;
this.kMTransX = this.kMTransY = this.kMSkewX =
this.kMSkewY = this.kMPersp0 = this.kMPersp1 = 0;
this._setTypeMask((int) TypeMask.kScale_Mask | kRectStaysRect_Mask);
}
}
void _setScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
this.reset();
}
else {
this._setScaleTranslate(sx, sy, px - sx * px, py - sy * py);
}
}
int _computeTypeMask() {
int mask = 0;
if (this.kMPersp0 != 0 || this.kMPersp1 != 0 ||
this.kMPersp2 != 1) {
// Once it is determined that that this is a perspective transform,
// all other flags are moot as far as optimizations are concerned.
return kORableMasks;
}
if (this.kMTransX != 0 || this.kMTransY != 0) {
mask |= (int) TypeMask.kTranslate_Mask;
}
int m00 = uiScalarUtils.ScalarAs2sCompliment(this.kMScaleX);
int m01 = uiScalarUtils.ScalarAs2sCompliment(this.kMSkewX);
int m10 = uiScalarUtils.ScalarAs2sCompliment(this.kMSkewY);
int m11 = uiScalarUtils.ScalarAs2sCompliment(this.kMScaleY);
if ((m01 != 0) | (m10 != 0)) {
mask |= (int) TypeMask.kAffine_Mask | (int) TypeMask.kScale_Mask;
m01 = m01 != 0 ? 1 : 0;
m10 = m10 != 0 ? 1 : 0;
int dp0 = 0 == (m00 | m11) ? 1 : 0;
int ds1 = m01 & m10;
mask |= (dp0 & ds1) << (int) TypeShift.kRectStaysRect_Shift;
}
else {
if (((m00 ^ kScalar1Int) | (m11 ^ kScalar1Int)) != 0) {
mask |= (int) TypeMask.kScale_Mask;
}
m00 = m00 != 0 ? 1 : 0;
m11 = m11 != 0 ? 1 : 0;
mask |= (m00 & m11) << (int) TypeShift.kRectStaysRect_Shift;
}
return mask;
}
TypeMask _getType() {
if ((this.fTypeMask & kUnknown_Mask) != 0) {
this.fTypeMask = this._computeTypeMask();
}
// only return the public masks
return (TypeMask) (this.fTypeMask & 0xF);
}
public void reset() {
this.kMScaleX = this.kMScaleY = this.kMPersp2 = 1;
this.kMSkewX = this.kMSkewY = this.kMTransX =
this.kMTransY = this.kMPersp0 = this.kMPersp1 = 0;
this._setTypeMask((int) TypeMask.kIdentity_Mask | kRectStaysRect_Mask);
}
bool _isTriviallyIdentity() {
if ((this.fTypeMask & kUnknown_Mask) != 0) {
return false;
}
return (this.fTypeMask & 0xF) == 0;
}
void _setConcat(uiMatrix3 a, uiMatrix3 b) {
TypeMask aType = a._getType();
TypeMask bType = b._getType();
if (a._isTriviallyIdentity()) {
this.copyFrom(b);
}
else if (b._isTriviallyIdentity()) {
this.copyFrom(a);
}
else if (_only_scale_and_translate((int) aType | (int) bType)) {
this._setScaleTranslate(a.kMScaleX * b.kMScaleX,
a.kMScaleY * b.kMScaleY,
a.kMScaleX * b.kMTransX + a.kMTransX,
a.kMScaleY * b.kMTransY + a.kMTransY);
}
else {
uiMatrix3 tmp = new uiMatrix3();
if (((aType | bType) & TypeMask.kPerspective_Mask) != 0) {
tmp.kMScaleX = _rowcol3(a, 0, b, 0);
tmp.kMSkewX = _rowcol3(a, 0, b, 1);
tmp.kMTransX = _rowcol3(a, 0, b, 2);
tmp.kMSkewY = _rowcol3(a, 3, b, 0);
tmp.kMScaleY = _rowcol3(a, 3, b, 1);
tmp.kMTransY = _rowcol3(a, 3, b, 2);
tmp.kMPersp0 = _rowcol3(a, 6, b, 0);
tmp.kMPersp1 = _rowcol3(a, 6, b, 1);
tmp.kMPersp2 = _rowcol3(a, 6, b, 2);
tmp._setTypeMask(kUnknown_Mask);
}
else {
tmp.kMScaleX = _muladdmul(a.kMScaleX,
b.kMScaleX,
a.kMSkewX,
b.kMSkewY);
tmp.kMSkewX = _muladdmul(a.kMScaleX,
b.kMSkewX,
a.kMSkewX,
b.kMScaleY);
tmp.kMTransX = _muladdmul(a.kMScaleX,
b.kMTransX,
a.kMSkewX,
b.kMTransY) + a.kMTransX;
tmp.kMSkewY = _muladdmul(a.kMSkewY,
b.kMScaleX,
a.kMScaleY,
b.kMSkewY);
tmp.kMScaleY = _muladdmul(a.kMSkewY,
b.kMSkewX,
a.kMScaleY,
b.kMScaleY);
tmp.kMTransY = _muladdmul(a.kMSkewY,
b.kMTransX,
a.kMScaleY,
b.kMTransY) + a.kMTransY;
tmp.kMPersp0 = 0;
tmp.kMPersp1 = 0;
tmp.kMPersp2 = 1;
tmp._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
this.copyFrom(tmp);
}
}
void _setScaleTranslate(float sx, float sy, float tx, float ty) {
this.kMScaleX = sx;
this.kMSkewX = 0;
this.kMTransX = tx;
this.kMSkewY = 0;
this.kMScaleY = sy;
this.kMTransY = ty;
this.kMPersp0 = 0;
this.kMPersp1 = 0;
this.kMPersp2 = 1;
int mask = 0;
if (sx != 1 || sy != 1) {
mask |= (int) TypeMask.kScale_Mask;
}
if (tx != 0 || ty != 0) {
mask |= (int) TypeMask.kTranslate_Mask;
}
this._setTypeMask(mask | kRectStaysRect_Mask);
}
void _setTypeMask(int mask) {
D.assert(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask) ==
(kUnknown_Mask | kOnlyPerspectiveValid_Mask));
this.fTypeMask = mask;
}
void _orTypeMask(int mask) {
D.assert((mask & kORableMasks) == mask);
this.fTypeMask |= mask;
}
void _clearTypeMask(int mask) {
// only allow a valid mask
D.assert((mask & kAllMasks) == mask);
this.fTypeMask &= ~mask;
}
int _computePerspectiveTypeMask() {
if (this.kMPersp0 != 0 || this.kMPersp1 != 0 ||
this.kMPersp2 != 1) {
return kORableMasks;
}
return kOnlyPerspectiveValid_Mask | kUnknown_Mask;
}
TypeMask _getPerspectiveTypeMaskOnly() {
if ((this.fTypeMask & kUnknown_Mask) != 0 &&
(this.fTypeMask & kOnlyPerspectiveValid_Mask) == 0) {
this.fTypeMask = this._computePerspectiveTypeMask();
}
return (TypeMask) (this.fTypeMask & 0xF);
}
bool _hasPerspective() {
return (this._getPerspectiveTypeMaskOnly() & TypeMask.kPerspective_Mask) != 0;
}
void _updateTranslateMask() {
if ((this.kMTransX != 0) | (this.kMTransY != 0)) {
this.fTypeMask |= (int) TypeMask.kTranslate_Mask;
}
else {
this.fTypeMask &= ~(int) TypeMask.kTranslate_Mask;
}
}
public bool _isFinite() {
return uiScalarUtils.ScalarsAreFinite(this);
}
uiMatrix3? _invertNonIdentity(bool invertableCheck) {
D.assert(!this.isIdentity());
TypeMask mask = this._getType();
if (0 == (mask & ~(TypeMask.kScale_Mask | TypeMask.kTranslate_Mask))) {
bool invertible = true;
if (!invertableCheck) {
if ((mask & TypeMask.kScale_Mask) != 0) {
var invX = this.kMScaleX;
var invY = this.kMScaleY;
if (0 == invX || 0 == invY) {
return null;
}
invX = 1f / invX;
invY = 1f / invY;
var _inv = I();
_inv.kMSkewX = _inv.kMSkewY =
_inv.kMPersp0 = _inv.kMPersp1 = 0;
_inv.kMScaleX = invX;
_inv.kMScaleY = invY;
_inv.kMPersp2 = 1;
_inv.kMTransX = -this.kMTransX * invX;
_inv.kMTransY = -this.kMTransY * invY;
_inv._setTypeMask((int) mask | kRectStaysRect_Mask);
return _inv;
}
else {
var _inv = I();
_inv.setTranslate(-this.kMTransX, -this.kMTransY);
return _inv;
}
}
else {
if (this.kMScaleX == 0 || this.kMScaleY == 0) {
return null;
}
return I();
}
}
int isPersp = (int) (mask & TypeMask.kPerspective_Mask);
float invDet = uiScalarUtils.inv_determinant(this, isPersp);
if (invDet == 0) {
// underflow
return null;
}
var inv = ComputeInv(this, invDet, isPersp != 0);
if (!inv._isFinite()) {
return null;
}
inv._setTypeMask(this.fTypeMask);
return inv;
}
public bool _isScaleTranslate() {
return (this._getType() & ~(TypeMask.kScale_Mask | TypeMask.kTranslate_Mask)) == 0;
}
public uiRect _mapRectScaleTranslate(uiRect src) {
D.assert(this._isScaleTranslate());
var sx = this.kMScaleX;
var sy = this.kMScaleY;
var tx = this.kMTransX;
var ty = this.kMTransY;
var dst = uiRectHelper.fromLTRB(
src.left * sx + tx,
src.top * sy + ty,
src.right * sx + tx,
src.bottom * sy + ty
);
dst = uiRectHelper.normalize(dst);
return dst;
}
}
public partial struct uiMatrix3 {
//public methods
public uiMatrix3(uiMatrix3 other) {
this.kMScaleX = other.kMScaleX;
this.kMSkewX = other.kMSkewX;
this.kMTransX = other.kMTransX;
this.kMSkewY = other.kMSkewY;
this.kMScaleY = other.kMScaleY;
this.kMTransY = other.kMTransY;
this.kMPersp0 = other.kMPersp0;
this.kMPersp1 = other.kMPersp1;
this.kMPersp2 = other.kMPersp2;
this.fTypeMask = other.fTypeMask;
}
public void copyFrom(uiMatrix3 other) {
this.kMScaleX = other.kMScaleX;
this.kMSkewX = other.kMSkewX;
this.kMTransX = other.kMTransX;
this.kMSkewY = other.kMSkewY;
this.kMScaleY = other.kMScaleY;
this.kMTransY = other.kMTransY;
this.kMPersp0 = other.kMPersp0;
this.kMPersp1 = other.kMPersp1;
this.kMPersp2 = other.kMPersp2;
this.fTypeMask = other.fTypeMask;
}
public bool isIdentity() {
return this._getType() == 0;
}
public float getScaleX() {
return this.kMScaleX;
}
public float getScaleY() {
return this.kMScaleY;
}
public float getSkewY() {
return this.kMSkewY;
}
public float getSkewX() {
return this.kMSkewX;
}
public float getTranslateX() {
return this.kMTransX;
}
public float getTranslateY() {
return this.kMTransY;
}
public float getPerspX() {
return this.kMPersp0;
}
public float getPerspY() {
return this.kMPersp1;
}
public void postConcat(uiMatrix3 mat) {
if (!mat.isIdentity()) {
this._setConcat(mat, this);
}
}
public void setSinCos(float sinV, float cosV, float px, float py) {
var oneMinusCosV = 1 - cosV;
this.kMScaleX = cosV;
this.kMSkewX = -sinV;
this.kMTransX = uiScalarUtils.sdot(sinV, py, oneMinusCosV, px);
this.kMSkewY = sinV;
this.kMScaleY = cosV;
this.kMTransY = uiScalarUtils.sdot(-sinV, px, oneMinusCosV, py);
this.kMPersp0 = this.kMPersp1 = 0;
this.kMPersp2 = 1;
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
public void setSinCos(float sinV, float cosV) {
this.kMScaleX = cosV;
this.kMSkewX = -sinV;
this.kMTransX = 0;
this.kMSkewY = sinV;
this.kMScaleY = cosV;
this.kMTransY = 0;
this.kMPersp0 = this.kMPersp1 = 0;
this.kMPersp2 = 1;
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
public void setTranslate(float dx, float dy) {
if ((dx != 0) | (dy != 0)) {
this.kMTransX = dx;
this.kMTransY = dy;
this.kMScaleX = this.kMScaleY = this.kMPersp2 = 1;
this.kMSkewX = this.kMSkewY =
this.kMPersp0 = this.kMPersp1 = 0;
this._setTypeMask((int) TypeMask.kTranslate_Mask | kRectStaysRect_Mask);
}
else {
this.reset();
}
}
public void postTranslate(float dx, float dy) {
if (this._hasPerspective()) {
var m = new uiMatrix3();
m.setTranslate(dx, dy);
this.postConcat(m);
}
else {
this.kMTransX += dx;
this.kMTransY += dy;
this._updateTranslateMask();
}
}
public void postScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
return;
}
var m = new uiMatrix3();
m._setScale(sx, sy);
this.postConcat(m);
}
public bool rectStaysRect() {
if ((this.fTypeMask & kUnknown_Mask) != 0) {
this.fTypeMask = this._computeTypeMask();
}
return (this.fTypeMask & kRectStaysRect_Mask) != 0;
}
public uiMatrix3? invert(bool invertableCheck = false) {
if (this.isIdentity()) {
return I();
}
return this._invertNonIdentity(invertableCheck);
}
public uiRect mapRect(uiRect src) {
if (this._getType() <= TypeMask.kTranslate_Mask) {
var tx = this.kMTransX;
var ty = this.kMTransY;
var dst = uiRectHelper.fromLTRB(
src.left + tx,
src.top + ty,
src.right + tx,
src.bottom + ty
);
dst = uiRectHelper.normalize(dst);
return dst;
}
if (this._isScaleTranslate()) {
return this._mapRectScaleTranslate(src);
}
else {
float x1, y1, x2, y2, x3, y3, x4, y4;
this.mapXY(src.left, src.top, out x1, out y1);
this.mapXY(src.right, src.top, out x2, out y2);
this.mapXY(src.right, src.bottom, out x3, out y3);
this.mapXY(src.left, src.bottom, out x4, out y4);
var minX = x1;
var minY = y1;
var maxX = x1;
var maxY = y1;
if (x2 < minX) {
minX = x2;
}
if (x2 > maxX) {
maxX = x2;
}
if (y2 < minY) {
minY = y2;
}
if (y2 > maxY) {
maxY = y2;
}
if (x3 < minX) {
minX = x3;
}
if (x3 > maxX) {
maxX = x3;
}
if (y3 < minY) {
minY = y3;
}
if (y3 > maxY) {
maxY = y3;
}
if (x4 < minX) {
minX = x4;
}
if (x4 > maxX) {
maxX = x4;
}
if (y4 < minY) {
minY = y4;
}
if (y4 > maxY) {
maxY = y4;
}
var dst = uiRectHelper.fromLTRB(minX, minY, maxX, maxY);
return dst;
}
}
public void mapXY(float x, float y, out float x1, out float y1) {
this._getMapXYProc()(this, x, y, out x1, out y1);
}
public Matrix4x4 toMatrix4x4() {
var matrix = Matrix4x4.identity;
matrix[0, 0] = this.kMScaleX; // row 0
matrix[0, 1] = this.kMSkewX;
matrix[0, 3] = this.kMTransX;
matrix[1, 0] = this.kMSkewY; // row 1
matrix[1, 1] = this.kMScaleY;
matrix[1, 3] = this.kMTransY;
matrix[3, 0] = this.kMPersp0; // row 2
matrix[3, 1] = this.kMPersp1;
matrix[3, 3] = this.kMPersp2;
return matrix;
}
public void preTranslate(float dx, float dy) {
var mask = this._getType();
if (mask <= TypeMask.kTranslate_Mask) {
this.kMTransX += dx;
this.kMTransY += dy;
}
else if ((mask & TypeMask.kPerspective_Mask) != 0) {
var m = new uiMatrix3();
m.setTranslate(dx, dy);
this.preConcat(m);
return;
}
else {
this.kMTransX += this.kMScaleX * dx + this.kMSkewX * dy;
this.kMTransY += this.kMSkewY * dx + this.kMScaleY * dy;
}
this._updateTranslateMask();
}
public void preConcat(uiMatrix3 other) {
if (!other.isIdentity()) {
this._setConcat(this, other);
}
}
public void preScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
return;
}
var m = new uiMatrix3();
m.setScale(sx, sy, px, py);
this.preConcat(m);
}
public void preScale(float sx, float sy) {
if (1 == sx && 1 == sy) {
return;
}
this.kMScaleX *= sx;
this.kMSkewY *= sx;
this.kMPersp0 *= sx;
this.kMSkewX *= sy;
this.kMScaleY *= sy;
this.kMPersp1 *= sy;
if (this.kMScaleX == 1 && this.kMScaleY == 1 && (this.fTypeMask &
(int) (TypeMask.kPerspective_Mask | TypeMask.kAffine_Mask)
) == 0) {
this._clearTypeMask((int) TypeMask.kScale_Mask);
}
else {
this._orTypeMask((int) TypeMask.kScale_Mask);
}
}
public void preRotate(float radians, float px, float py) {
var m = new uiMatrix3();
m.setRotate(radians, px, py);
this.preConcat(m);
}
public void preRotate(float radians) {
var m = new uiMatrix3();
m.setRotate(radians);
this.preConcat(m);
}
public void preSkew(float kx, float ky) {
var m = new uiMatrix3();
m.setSkew(kx, ky);
this.preConcat(m);
}
public void setScale(float sx, float sy, float px, float py) {
if (1 == sx && 1 == sy) {
this.reset();
}
else {
this._setScaleTranslate(sx, sy, px - sx * px, py - sy * py);
}
}
}
}

572
Runtime/ui/renderer/common/geometry/matrix/ui_matrix_utils.cs


using System;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public partial struct uiMatrix3 {
public void mapPoints(uiOffset[] dst, uiOffset[] src) {
D.assert(dst != null && src != null && dst.Length == src.Length);
this._getMapPtsProc()(this, dst, src, src.Length);
}
public void mapPoints(uiOffset[] pts) {
this.mapPoints(pts, pts);
}
delegate void MapPtsProc(uiMatrix3 mat, uiOffset[] dst, uiOffset[] src, int count);
static readonly MapPtsProc[] gMapPtsProcs = {
Identity_pts, Trans_pts,
Scale_pts, Scale_pts,
Affine_pts, Affine_pts,
Affine_pts, Affine_pts,
// repeat the persp proc 8 times
Persp_pts, Persp_pts,
Persp_pts, Persp_pts,
Persp_pts, Persp_pts,
Persp_pts, Persp_pts
};
static MapPtsProc GetMapPtsProc(TypeMask mask) {
D.assert(((int) mask & ~kAllMasks) == 0);
return gMapPtsProcs[(int) mask & kAllMasks];
}
MapPtsProc _getMapPtsProc() {
return GetMapPtsProc(this._getType());
}
static void Identity_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) {
D.assert(m._getType() == 0);
if (dst != src && count > 0) {
Array.Copy(src, dst, count);
}
}
static void Trans_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) {
D.assert(m._getType() <= TypeMask.kTranslate_Mask);
if (count > 0) {
var tx = m.getTranslateX();
var ty = m.getTranslateY();
for (int i = 0; i < count; ++i) {
dst[i] = new uiOffset(src[i].dx + tx, src[i].dy + ty);
}
}
}
static void Scale_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) {
D.assert(m._getType() <= (TypeMask.kScale_Mask | TypeMask.kTranslate_Mask));
if (count > 0) {
var tx = m.getTranslateX();
var ty = m.getTranslateY();
var sx = m.getScaleX();
var sy = m.getScaleY();
for (int i = 0; i < count; ++i) {
dst[i] = new uiOffset(src[i].dx * sx + tx, src[i].dy * sy + ty);
}
}
}
static void Persp_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) {
D.assert(m._hasPerspective());
if (count > 0) {
for (int i = 0; i < count; ++i) {
var sy = src[i].dy;
var sx = src[i].dx;
var x = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) +
m.kMTransX;
var y = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) +
m.kMTransY;
var z = uiScalarUtils.sdot(sx, m.kMPersp0, sy, m.kMPersp1) +
m.kMPersp2;
if (z != 0) {
z = 1 / z;
}
dst[i] = new uiOffset(x * z, y * z);
}
}
}
static void Affine_pts(uiMatrix3 m, uiOffset[] dst, uiOffset[] src, int count) {
D.assert(m._getType() != TypeMask.kPerspective_Mask);
if (count > 0) {
var tx = m.getTranslateX();
var ty = m.getTranslateY();
var sx = m.getScaleX();
var sy = m.getScaleY();
var kx = m.getSkewX();
var ky = m.getSkewY();
for (int i = 0; i < count; ++i) {
dst[i] = new uiOffset(
src[i].dx * sx + src[i].dy * kx + tx,
src[i].dx * ky + src[i].dy * sy + ty);
}
}
}
}
public partial struct uiMatrix3 {
delegate void MapXYProc(uiMatrix3 mat, float x, float y, out float x1, out float y1);
static readonly MapXYProc[] gMapXYProcs = {
Identity_xy, Trans_xy,
Scale_xy, ScaleTrans_xy,
Rot_xy, RotTrans_xy,
Rot_xy, RotTrans_xy,
// repeat the persp proc 8 times
Persp_xy, Persp_xy,
Persp_xy, Persp_xy,
Persp_xy, Persp_xy,
Persp_xy, Persp_xy
};
static MapXYProc GetMapXYProc(TypeMask mask) {
D.assert(((int) mask & ~kAllMasks) == 0);
return gMapXYProcs[(int) mask & kAllMasks];
}
MapXYProc _getMapXYProc() {
return GetMapXYProc(this._getType());
}
static void Identity_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert(0 == m._getType());
resX = sx;
resY = sy;
}
static void Trans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert(m._getType() == TypeMask.kTranslate_Mask);
resX = sx + m.kMTransX;
resY = sy + m.kMTransY;
}
static void Scale_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert((m._getType() & (TypeMask.kScale_Mask | TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask))
== TypeMask.kScale_Mask);
D.assert(0 == m.kMTransX);
D.assert(0 == m.kMTransY);
resX = sx * m.kMScaleX;
resY = sy * m.kMScaleY;
}
static void ScaleTrans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert((m._getType() & (TypeMask.kScale_Mask | TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask))
== TypeMask.kScale_Mask);
resX = sx * m.kMScaleX + m.kMTransX;
resY = sy * m.kMScaleY + m.kMTransY;
}
static void Rot_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert((m._getType() & (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) == TypeMask.kAffine_Mask);
D.assert(0 == m.kMTransX);
D.assert(0 == m.kMTransY);
resX = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX);
resY = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY);
}
static void RotTrans_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert((m._getType() & (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask)) == TypeMask.kAffine_Mask);
resX = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) + m.kMTransX;
resY = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) + m.kMTransY;
}
static void Persp_xy(uiMatrix3 m, float sx, float sy, out float resX, out float resY) {
D.assert(m._hasPerspective());
float x = uiScalarUtils.sdot(sx, m.kMScaleX, sy, m.kMSkewX) +
m.kMTransX;
float y = uiScalarUtils.sdot(sx, m.kMSkewY, sy, m.kMScaleY) +
m.kMTransY;
float z = uiScalarUtils.sdot(sx, m.kMPersp0, sy, m.kMPersp1) +
m.kMPersp2;
if (z != 0) {
z = 1 / z;
}
resX = x * z;
resY = y * z;
}
}
public partial struct uiMatrix3 {
//static methods
public static uiMatrix3 I() {
var m = new uiMatrix3();
m.reset();
return m;
}
public static uiMatrix3 makeTrans(float dx, float dy) {
var m = new uiMatrix3();
m.setTranslate(dx, dy);
return m;
}
public static uiMatrix3 makeScale(float sx, float sy) {
var m = new uiMatrix3();
m._setScale(sx, sy);
return m;
}
public static uiMatrix3 makeRotate(float radians) {
var m = new uiMatrix3();
m.setRotate(radians);
return m;
}
public static uiMatrix3 makeRotate(float radians, float px, float py) {
var m = new uiMatrix3();
m.setRotate(radians, px, py);
return m;
}
public static uiMatrix3 makeTrans(uiOffset offset) {
var m = new uiMatrix3();
m.setTranslate(offset.dx, offset.dy);
return m;
}
public static uiMatrix3 makeSkew(float dx, float dy) {
var m = new uiMatrix3();
m.setSkew(dx, dy);
return m;
}
public static uiMatrix3 concat(uiMatrix3 a, uiMatrix3 b) {
uiMatrix3 result = I();
result._setConcat(a, b);
return result;
}
public void setRotate(float radians, float px, float py) {
float sinV, cosV;
sinV = uiScalarUtils.ScalarSinCos(radians, out cosV);
this.setSinCos(sinV, cosV, px, py);
}
public void setRotate(float radians) {
float sinV, cosV;
sinV = uiScalarUtils.ScalarSinCos(radians, out cosV);
this.setSinCos(sinV, cosV);
}
public void setSkew(float kx, float ky, float px, float py) {
this.kMScaleX = 1;
this.kMSkewX = kx;
this.kMTransX = -kx * py;
this.kMSkewY = ky;
this.kMScaleY = 1;
this.kMTransY = -ky * px;
this.kMPersp0 = this.kMPersp1 = 0;
this.kMPersp2 = 1;
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
public void setSkew(float kx, float ky) {
this.kMScaleX = 1;
this.kMSkewX = kx;
this.kMTransX = 0;
this.kMSkewY = ky;
this.kMScaleY = 1;
this.kMTransY = 0;
this.kMPersp0 = this.kMPersp1 = 0;
this.kMPersp2 = 1;
this._setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
public static bool equals(uiMatrix3? a, uiMatrix3? b) {
if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) {
return true;
}
if (ReferenceEquals(a, b)) {
return true;
}
if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) {
return false;
}
var ma = a.Value;
var mb = b.Value;
return ma.kMScaleX == mb.kMScaleX && ma.kMSkewX == mb.kMSkewX && ma.kMTransX == mb.kMTransX &&
ma.kMSkewY == mb.kMSkewY && ma.kMScaleY == mb.kMScaleY && ma.kMTransY == mb.kMTransY &&
ma.kMPersp0 == mb.kMPersp0 && ma.kMPersp1 == mb.kMPersp1 && ma.kMPersp2 == mb.kMPersp2;
}
}
public partial struct uiMatrix3 {
public static uiMatrix3 fromMatrix3(Matrix3 mat3) {
var uiMat3 = I();
uiMat3.kMScaleX = mat3[0];
uiMat3.kMSkewX = mat3[1];
uiMat3.kMTransX = mat3[2];
uiMat3.kMSkewY = mat3[3];
uiMat3.kMScaleY = mat3[4];
uiMat3.kMTransY = mat3[5];
uiMat3.kMPersp0 = mat3[6];
uiMat3.kMPersp1 = mat3[7];
uiMat3.kMPersp2 = mat3[8];
uiMat3._setTypeMask(kUnknown_Mask);
return uiMat3;
}
static bool _only_scale_and_translate(int mask) {
return 0 == (mask & (int) (TypeMask.kAffine_Mask | TypeMask.kPerspective_Mask));
}
static float _getitem(uiMatrix3 mat, int i) {
switch (i) {
case 0:
return mat.kMScaleX;
case 1:
return mat.kMSkewX;
case 2:
return mat.kMTransX;
case 3:
return mat.kMSkewY;
case 4:
return mat.kMScaleY;
case 5:
return mat.kMTransY;
case 6:
return mat.kMPersp0;
case 7:
return mat.kMPersp1;
case 8:
return mat.kMPersp2;
default: {
return -1;
}
}
}
static float _rowcol3(uiMatrix3 row, int i, uiMatrix3 col, int j) {
return _getitem(row, i) * _getitem(col, j) + _getitem(row, i + 1) * _getitem(col, j + 3) +
_getitem(row, i + 2) * _getitem(col, j + 6);
}
static float _muladdmul(float a, float b, float c, float d) {
return (float) ((double) a * b + (double) c * d);
}
static uiMatrix3 ComputeInv(uiMatrix3 src, float invDet, bool isPersp) {
uiMatrix3 dst = I();
if (isPersp) {
dst.kMScaleX =
uiScalarUtils.scross_dscale(src.kMScaleY, src.kMPersp2, src.kMTransY,
src.kMPersp1, invDet);
dst.kMSkewX =
uiScalarUtils.scross_dscale(src.kMTransX, src.kMPersp1, src.kMSkewX,
src.kMPersp2, invDet);
dst.kMTransX =
uiScalarUtils.scross_dscale(src.kMSkewX, src.kMTransY, src.kMTransX,
src.kMScaleY, invDet);
dst.kMSkewY =
uiScalarUtils.scross_dscale(src.kMTransY, src.kMPersp0, src.kMSkewY,
src.kMPersp2, invDet);
dst.kMScaleY =
uiScalarUtils.scross_dscale(src.kMScaleX, src.kMPersp2, src.kMTransX,
src.kMPersp0, invDet);
dst.kMTransY =
uiScalarUtils.scross_dscale(src.kMTransX, src.kMSkewY, src.kMScaleX,
src.kMTransY, invDet);
dst.kMPersp0 =
uiScalarUtils.scross_dscale(src.kMSkewY, src.kMPersp1, src.kMScaleY,
src.kMPersp0, invDet);
dst.kMPersp1 =
uiScalarUtils.scross_dscale(src.kMSkewX, src.kMPersp0, src.kMScaleX,
src.kMPersp1, invDet);
dst.kMPersp2 =
uiScalarUtils.scross_dscale(src.kMScaleX, src.kMScaleY, src.kMSkewX,
src.kMSkewY, invDet);
}
else {
// not perspective
dst.kMScaleX = src.kMScaleY * invDet;
dst.kMSkewX = -src.kMSkewX * invDet;
dst.kMTransX =
uiScalarUtils.dcross_dscale(src.kMSkewX, src.kMTransY, src.kMScaleY,
src.kMTransX, invDet);
dst.kMSkewY = -src.kMSkewY * invDet;
dst.kMScaleY = src.kMScaleX * invDet;
dst.kMTransY =
uiScalarUtils.dcross_dscale(src.kMSkewY, src.kMTransX, src.kMScaleX,
src.kMTransY, invDet);
dst.kMPersp0 = 0;
dst.kMPersp1 = 0;
dst.kMPersp2 = 1;
}
return dst;
}
//utils
class uiScalarUtils {
public const float kScalarNearlyZero = 1f / (1 << 12);
public static bool ScalarNearlyZero(float x, float tolerance = kScalarNearlyZero) {
D.assert(tolerance >= 0);
return Mathf.Abs(x) <= tolerance;
}
public static bool ScalarNearlyEqual(float x, float y, float tolerance = kScalarNearlyZero) {
D.assert(tolerance >= 0);
return Mathf.Abs(x - y) <= tolerance;
}
public static bool ScalarIsInteger(float scalar) {
return scalar == Mathf.FloorToInt(scalar);
}
public static float DegreesToRadians(float degrees) {
return degrees * (Mathf.PI / 180);
}
public static float RadiansToDegrees(float radians) {
return radians * (180 / Mathf.PI);
}
public static float ScalarSinCos(float radians, out float cosValue) {
float sinValue = Mathf.Sin(radians);
cosValue = Mathf.Cos(radians);
if (ScalarNearlyZero(cosValue)) {
cosValue = 0;
}
if (ScalarNearlyZero(sinValue)) {
sinValue = 0;
}
return sinValue;
}
public static bool ScalarsAreFinite(uiMatrix3 m) {
float prod = m.kMScaleX * m.kMSkewX * m.kMTransX * m.kMSkewY * m.kMScaleY * m.kMTransY * m.kMPersp0 *
m.kMPersp1 * m.kMPersp2;
// At this point, prod will either be NaN or 0
return prod == 0; // if prod is NaN, this check will return false
}
static byte[] _scalar_as_2s_compliment_vars = new byte[4];
static unsafe int GetBytesToInt32(float value) {
var intVal = *(int*) &value;
fixed (byte* b = _scalar_as_2s_compliment_vars) {
*((int*) b) = intVal;
}
fixed (byte* pbyte = &_scalar_as_2s_compliment_vars[0]) {
return *((int*) pbyte);
}
}
public static int ScalarAs2sCompliment(float x) {
var result = GetBytesToInt32(x);
if (result < 0) {
result &= 0x7FFFFFFF;
result = -result;
}
return result;
}
public static float sdot(float a, float b, float c, float d) {
return a * b + c * d;
}
public static float sdot(float a, float b, float c, float d, float e, float f) {
return a * b + c * d + e * f;
}
public static float scross(float a, float b, float c, float d) {
return a * b - c * d;
}
public static double dcross(double a, double b, double c, double d) {
return a * b - c * d;
}
public static float scross_dscale(float a, float b,
float c, float d, double scale) {
return (float) (scross(a, b, c, d) * scale);
}
public static float dcross_dscale(double a, double b,
double c, double d, double scale) {
return (float) (dcross(a, b, c, d) * scale);
}
public static bool is_degenerate_2x2(
float scaleX, float skewX,
float skewY, float scaleY) {
float perp_dot = scaleX * scaleY - skewX * skewY;
return ScalarNearlyZero(perp_dot,
kScalarNearlyZero * kScalarNearlyZero);
}
public static float inv_determinant(uiMatrix3 mat, int isPerspective) {
double det;
if (isPerspective != 0) {
det = mat.kMScaleX *
dcross(mat.kMScaleY, mat.kMPersp2,
mat.kMTransY, mat.kMPersp1)
+
mat.kMSkewX *
dcross(mat.kMTransY, mat.kMPersp0,
mat.kMSkewY, mat.kMPersp2)
+
mat.kMTransX *
dcross(mat.kMSkewY, mat.kMPersp1,
mat.kMScaleY, mat.kMPersp0);
}
else {
det = dcross(mat.kMScaleX, mat.kMScaleY,
mat.kMSkewX, mat.kMSkewY);
}
// Since the determinant is on the order of the cube of the matrix members,
// compare to the cube of the default nearly-zero constant (although an
// estimate of the condition number would be better if it wasn't so expensive).
if (ScalarNearlyZero((float) det,
kScalarNearlyZero * kScalarNearlyZero * kScalarNearlyZero)) {
return 0;
}
return 1.0f / (float) det;
}
}
}
}

147
Runtime/ui/renderer/common/geometry/mesh_mesh.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class uiMeshMesh : PoolObject {
public uiList<Vector3> vertices;
public uiList<int> triangles;
public uiList<Vector2> uv;
public uiMatrix3? matrix;
public uiRect rawBounds;
uiRect? _bounds;
public uiRect bounds {
get {
if (this._bounds == null) {
this._bounds = this.matrix != null ? this.matrix.Value.mapRect(this.rawBounds) : this.rawBounds;
}
return this._bounds.Value;
}
}
static readonly List<int> _boundsTriangles = new List<int>(6) {
0, 2, 1, 1, 2, 3
};
public uiMeshMesh boundsMesh {
get { return create(this.bounds); }
}
public uiMeshMesh() {
}
public override void clear() {
ObjectPool<uiList<Vector3>>.release(this.vertices);
ObjectPool<uiList<int>>.release(this.triangles);
ObjectPool<uiList<Vector2>>.release(this.uv);
this.vertices = null;
this.triangles = null;
this.uv = null;
this.matrix = null;
this._bounds = null;
}
public static uiMeshMesh create(uiRect rect) {
uiMeshMesh newMesh = ObjectPool<uiMeshMesh>.alloc();
newMesh.vertices = ObjectPool<uiList<Vector3>>.alloc();
newMesh.vertices.Add(new Vector3(rect.right, rect.bottom));
newMesh.vertices.Add(new Vector3(rect.right, rect.top));
newMesh.vertices.Add(new Vector3(rect.left, rect.bottom));
newMesh.vertices.Add(new Vector3(rect.left, rect.top));
newMesh.triangles = ObjectPool<uiList<int>>.alloc();
newMesh.triangles.AddRange(_boundsTriangles);
newMesh.rawBounds = rect;
newMesh._bounds = newMesh.rawBounds;
return newMesh;
}
public static uiMeshMesh create(uiMatrix3? matrix, uiList<Vector3> vertices, uiList<int> triangles,
uiList<Vector2> uv = null,
uiRect? rawBounds = null) {
D.assert(vertices != null);
D.assert(vertices.Count >= 0);
D.assert(triangles != null);
D.assert(triangles.Count >= 0);
D.assert(uv == null || uv.Count == vertices.Count);
uiMeshMesh newMesh = ObjectPool<uiMeshMesh>.alloc();
newMesh.matrix = matrix;
newMesh.vertices = vertices;
newMesh.triangles = triangles;
if (uv != null) {
newMesh.uv = uv;
}
if (rawBounds == null) {
if (vertices.Count > 0) {
float minX = vertices[0].x;
float maxX = vertices[0].x;
float minY = vertices[0].y;
float maxY = vertices[0].y;
for (int i = 1; i < vertices.Count; i++) {
var vertex = vertices[i];
if (vertex.x < minX) {
minX = vertex.x;
}
if (vertex.x > maxX) {
maxX = vertex.x;
}
if (vertex.y < minY) {
minY = vertex.y;
}
if (vertex.y > maxY) {
maxY = vertex.y;
}
}
rawBounds = uiRectHelper.fromLTRB(minX, minY, maxX, maxY);
}
else {
rawBounds = uiRectHelper.zero;
}
}
newMesh.rawBounds = rawBounds.Value;
return newMesh;
}
public uiMeshMesh duplicate() {
return this.transform(this.matrix);
}
public uiMeshMesh transform(uiMatrix3? matrix) {
var vertices = ObjectPool<uiList<Vector3>>.alloc();
vertices.SetCapacity(this.vertices.Count);
vertices.AddRange(this.vertices.data);
var triangles = ObjectPool<uiList<int>>.alloc();
triangles.SetCapacity(this.triangles.Count);
triangles.AddRange(this.triangles.data);
uiList<Vector2> uv = null;
if (this.uv != null) {
uv = ObjectPool<uiList<Vector2>>.alloc();
uv.SetCapacity(this.uv.Count);
uv.AddRange(this.uv.data);
}
var ret = create(matrix, vertices, triangles, uv, this.rawBounds);
return ret;
}
}
}

25
Runtime/ui/renderer/common/geometry/offset.cs


namespace Unity.UIWidgets.ui {
public struct uiOffset {
public uiOffset(float dx, float dy) {
this.dx = dx;
this.dy = dy;
}
public readonly float dx;
public readonly float dy;
public static uiOffset? fromOffset(Offset offset) {
if (offset == null) {
return null;
}
var newOffset = new uiOffset(offset.dx, offset.dy);
return newOffset;
}
public static uiOffset operator -(uiOffset a) {
return new uiOffset(-a.dx, -a.dy);
}
}
}

11
Runtime/ui/renderer/common/geometry/path/path.cs.meta


fileFormatVersion: 2
guid: 474119e5987c445ec9c091013283edf4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/path/path_cache.cs.meta


fileFormatVersion: 2
guid: 56917523cf9a4442e9f6ab6f24772946
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/path/path_utils.cs.meta


fileFormatVersion: 2
guid: 5d69fe5c05f3d4bd69d76f795f95964d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs.meta


fileFormatVersion: 2
guid: c40e07520bc854d85b57d0021c9bfba6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

422
Runtime/ui/renderer/common/geometry/path/path.cs


using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public class uiPath : PoolObject {
const float _KAPPA90 = 0.5522847493f;
uiList<float> _commands;
float _commandx;
float _commandy;
float _minX, _minY;
float _maxX, _maxY;
uiPathCache _cache;
public uint pathKey = 0;
public bool needCache = false;
public static uiPath create(int capacity = 128) {
uiPath newPath = ObjectPool<uiPath>.alloc();
newPath._reset();
return newPath;
}
public uiPath() {
}
public override void clear() {
ObjectPool<uiList<float>>.release(this._commands);
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
this._commands = null;
this.needCache = false;
this.pathKey = 0;
}
void _reset() {
this._commands = ObjectPool<uiList<float>>.alloc();
this._commandx = 0;
this._commandy = 0;
this._minX = float.MaxValue;
this._minY = float.MaxValue;
this._maxX = float.MinValue;
this._maxY = float.MinValue;
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
internal uiPathCache flatten(float scale) {
scale = Mathf.Round(scale * 2.0f) / 2.0f; // round to 0.5f
if (this._cache != null && this._cache.canReuse(scale)) {
return this._cache;
}
var _cache = uiPathCache.create(scale);
var i = 0;
while (i < this._commands.Count) {
var cmd = (uiPathCommand) this._commands[i];
switch (cmd) {
case uiPathCommand.moveTo:
_cache.addPath();
_cache.addPoint(this._commands[i + 1], this._commands[i + 2], uiPointFlags.corner);
i += 3;
break;
case uiPathCommand.lineTo:
_cache.addPoint(this._commands[i + 1], this._commands[i + 2], uiPointFlags.corner);
i += 3;
break;
case uiPathCommand.bezierTo:
_cache.tessellateBezier(
this._commands[i + 1], this._commands[i + 2],
this._commands[i + 3], this._commands[i + 4],
this._commands[i + 5], this._commands[i + 6], uiPointFlags.corner);
i += 7;
break;
case uiPathCommand.close:
_cache.closePath();
i++;
break;
case uiPathCommand.winding:
_cache.pathWinding((uiPathWinding) this._commands[i + 1]);
i += 2;
break;
default:
D.assert(false, () => "unknown cmd: " + cmd);
break;
}
}
_cache.normalize();
ObjectPool<uiPathCache>.release(this._cache);
this._cache = _cache;
return _cache;
}
void _expandBounds(float x, float y) {
if (x < this._minX) {
this._minX = x;
}
if (y < this._minY) {
this._minY = y;
}
if (x > this._maxX) {
this._maxX = x;
}
if (y > this._maxY) {
this._maxY = y;
}
}
void _appendMoveTo(float x, float y) {
this._commands.Add((float) uiPathCommand.moveTo);
this._commands.Add(x);
this._commands.Add(y);
this._commandx = x;
this._commandy = y;
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
void _appendLineTo(float x, float y) {
this._expandBounds(this._commandx, this._commandy);
this._expandBounds(x, y);
this._commands.Add((float) uiPathCommand.lineTo);
this._commands.Add(x);
this._commands.Add(y);
this._commandx = x;
this._commandy = y;
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
void _appendBezierTo(float x1, float y1, float x2, float y2, float x3, float y3) {
this._expandBounds(this._commandx, this._commandy);
this._expandBounds(x1, y1);
this._expandBounds(x2, y2);
this._expandBounds(x3, y3);
this._commands.Add((float) uiPathCommand.bezierTo);
this._commands.Add(x1);
this._commands.Add(y1);
this._commands.Add(x2);
this._commands.Add(y2);
this._commands.Add(x3);
this._commands.Add(y3);
this._commandx = x3;
this._commandy = y3;
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
void _appendClose() {
this._commands.Add((float) uiPathCommand.close);
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
void _appendWinding(float winding) {
this._commands.Add((float) uiPathCommand.winding);
this._commands.Add(winding);
ObjectPool<uiPathCache>.release(this._cache);
this._cache = null;
}
public void addRect(uiRect rect) {
this._appendMoveTo(rect.left, rect.top);
this._appendLineTo(rect.left, rect.bottom);
this._appendLineTo(rect.right, rect.bottom);
this._appendLineTo(rect.right, rect.top);
this._appendClose();
}
public void addRect(Rect rect) {
this._appendMoveTo(rect.left, rect.top);
this._appendLineTo(rect.left, rect.bottom);
this._appendLineTo(rect.right, rect.bottom);
this._appendLineTo(rect.right, rect.top);
this._appendClose();
}
public void addRRect(RRect rrect) {
float w = rrect.width;
float h = rrect.height;
float halfw = Mathf.Abs(w) * 0.5f;
float halfh = Mathf.Abs(h) * 0.5f;
float signW = Mathf.Sign(w);
float signH = Mathf.Sign(h);
float rxBL = Mathf.Min(rrect.blRadiusX, halfw) * signW;
float ryBL = Mathf.Min(rrect.blRadiusY, halfh) * signH;
float rxBR = Mathf.Min(rrect.brRadiusX, halfw) * signW;
float ryBR = Mathf.Min(rrect.brRadiusY, halfh) * signH;
float rxTR = Mathf.Min(rrect.trRadiusX, halfw) * signW;
float ryTR = Mathf.Min(rrect.trRadiusY, halfh) * signH;
float rxTL = Mathf.Min(rrect.tlRadiusX, halfw) * signW;
float ryTL = Mathf.Min(rrect.tlRadiusY, halfh) * signH;
float x = rrect.left;
float y = rrect.top;
this._appendMoveTo(x, y + ryTL);
this._appendLineTo(x, y + h - ryBL);
this._appendBezierTo(x, y + h - ryBL * (1 - _KAPPA90),
x + rxBL * (1 - _KAPPA90), y + h, x + rxBL, y + h);
this._appendLineTo(x + w - rxBR, y + h);
this._appendBezierTo(x + w - rxBR * (1 - _KAPPA90), y + h,
x + w, y + h - ryBR * (1 - _KAPPA90), x + w, y + h - ryBR);
this._appendLineTo(x + w, y + ryTR);
this._appendBezierTo(x + w, y + ryTR * (1 - _KAPPA90),
x + w - rxTR * (1 - _KAPPA90), y, x + w - rxTR, y);
this._appendLineTo(x + rxTL, y);
this._appendBezierTo(x + rxTL * (1 - _KAPPA90), y,
x, y + ryTL * (1 - _KAPPA90), x, y + ryTL);
this._appendClose();
}
public void moveTo(float x, float y) {
this._appendMoveTo(x, y);
}
public void lineTo(float x, float y) {
this._appendLineTo(x, y);
}
public void winding(PathWinding dir) {
this._appendWinding((float) dir);
}
public void addEllipse(float cx, float cy, float rx, float ry) {
this._appendMoveTo(cx - rx, cy);
this._appendBezierTo(cx - rx, cy + ry * _KAPPA90,
cx - rx * _KAPPA90, cy + ry, cx, cy + ry);
this._appendBezierTo(cx + rx * _KAPPA90, cy + ry,
cx + rx, cy + ry * _KAPPA90, cx + rx, cy);
this._appendBezierTo(cx + rx, cy - ry * _KAPPA90,
cx + rx * _KAPPA90, cy - ry, cx, cy - ry);
this._appendBezierTo(cx - rx * _KAPPA90, cy - ry,
cx - rx, cy - ry * _KAPPA90, cx - rx, cy);
this._appendClose();
}
public void addCircle(float cx, float cy, float r) {
this.addEllipse(cx, cy, r, r);
}
public void arcTo(Rect rect, float startAngle, float sweepAngle, bool forceMoveTo = true) {
var mat = Matrix3.makeScale(rect.width / 2, rect.height / 2);
var center = rect.center;
mat.postTranslate(center.dx, center.dy);
this._addArcCommands(0, 0, 1, startAngle, startAngle + sweepAngle,
sweepAngle >= 0 ? PathWinding.clockwise : PathWinding.counterClockwise, forceMoveTo, mat);
}
public void close() {
this._appendClose();
}
void _addArcCommands(
float cx, float cy, float r, float a0, float a1,
PathWinding dir, bool forceMoveTo, Matrix3 transform = null) {
// Clamp angles
float da = a1 - a0;
if (dir == PathWinding.clockwise) {
if (Mathf.Abs(da) >= Mathf.PI * 2) {
da = Mathf.PI * 2;
}
else {
while (da < 0.0f) {
da += Mathf.PI * 2;
}
if (da <= 1e-5) {
return;
}
}
}
else {
if (Mathf.Abs(da) >= Mathf.PI * 2) {
da = -Mathf.PI * 2;
}
else {
while (da > 0.0f) {
da -= Mathf.PI * 2;
}
if (da >= -1e-5) {
return;
}
}
}
// Split arc into max 90 degree segments.
int ndivs = Mathf.Max(1, Mathf.Min((int) (Mathf.Abs(da) / (Mathf.PI * 0.5f) + 0.5f), 5));
float hda = (da / ndivs) / 2.0f;
float kappa = Mathf.Abs(4.0f / 3.0f * (1.0f - Mathf.Cos(hda)) / Mathf.Sin(hda));
if (dir == PathWinding.counterClockwise) {
kappa = -kappa;
}
PathCommand move = (forceMoveTo || this._commands.Count == 0) ? PathCommand.moveTo : PathCommand.lineTo;
float px = 0, py = 0, ptanx = 0, ptany = 0;
for (int i = 0; i <= ndivs; i++) {
float a = a0 + da * (i / (float) ndivs);
float dx = Mathf.Cos(a);
float dy = Mathf.Sin(a);
float x = cx + dx * r;
float y = cy + dy * r;
float tanx = -dy * r * kappa;
float tany = dx * r * kappa;
if (i == 0) {
float x1 = x, y1 = y;
if (transform != null) {
transform.mapXY(x1, y1, out x1, out y1);
}
if (move == PathCommand.moveTo) {
this._appendMoveTo(x1, y1);
}
else {
this._appendLineTo(x1, y1);
}
}
else {
float c1x = px + ptanx;
float c1y = py + ptany;
float c2x = x - tanx;
float c2y = y - tany;
float x1 = x;
float y1 = y;
if (transform != null) {
transform.mapXY(c1x, c1y, out c1x, out c1y);
transform.mapXY(c2x, c2y, out c2x, out c2y);
transform.mapXY(x1, y1, out x1, out y1);
}
this._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1);
}
px = x;
py = y;
ptanx = tanx;
ptany = tany;
}
}
public static uiPath fromPath(Path path) {
D.assert(path != null);
uiPath uipath;
bool exists = uiPathCacheManager.tryGetUiPath(path.pathKey, out uipath);
if (exists) {
return uipath;
}
var i = 0;
var _commands = path.commands;
while (i < _commands.Count) {
var cmd = (uiPathCommand) _commands[i];
switch (cmd) {
case uiPathCommand.moveTo: {
float x = _commands[i + 1];
float y = _commands[i + 2];
uipath._appendMoveTo(x, y);
}
i += 3;
break;
case uiPathCommand.lineTo: {
float x = _commands[i + 1];
float y = _commands[i + 2];
uipath._appendLineTo(x, y);
}
i += 3;
break;
case uiPathCommand.bezierTo: {
float c1x = _commands[i + 1];
float c1y = _commands[i + 2];
float c2x = _commands[i + 3];
float c2y = _commands[i + 4];
float x1 = _commands[i + 5];
float y1 = _commands[i + 6];
uipath._appendBezierTo(c1x, c1y, c2x, c2y, x1, y1);
}
i += 7;
break;
case uiPathCommand.close:
uipath._appendClose();
i++;
break;
case uiPathCommand.winding:
uipath._appendWinding(_commands[i + 1]);
i += 2;
break;
default:
D.assert(false, () => "unknown cmd: " + cmd);
break;
}
}
return uipath;
}
}
}

563
Runtime/ui/renderer/common/geometry/path/path_cache.cs


using System.Collections.Generic;
using Unity.UIWidgets.foundation;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class uiPathCache : PoolObject {
float _distTol;
float _tessTol;
List<uiPathPath> _paths = new List<uiPathPath>();
List<uiPathPoint> _points = new List<uiPathPoint>();
float _scale;
//mesh cache
uiMeshMesh _fillMesh;
bool _fillConvex;
uiMeshMesh _strokeMesh;
float _strokeWidth;
StrokeCap _lineCap;
StrokeJoin _lineJoin;
float _miterLimit;
public static uiPathCache create(float scale) {
uiPathCache newPathCache = ObjectPool<uiPathCache>.alloc();
newPathCache._distTol = 0.01f / scale;
newPathCache._tessTol = 0.25f / scale;
newPathCache._scale = scale;
return newPathCache;
}
public bool canReuse(float scale) {
if (this._scale != scale) {
return false;
}
return true;
}
public override void clear() {
this._paths.Clear();
this._points.Clear();
ObjectPool<uiMeshMesh>.release(this._fillMesh);
this._fillMesh = null;
ObjectPool<uiMeshMesh>.release(this._strokeMesh);
this._strokeMesh = null;
}
public uiPathCache() {
}
public void addPath() {
this._paths.Add(uiPathPath.create(
first: this._points.Count,
winding: uiPathWinding.counterClockwise
));
}
public void addPoint(float x, float y, uiPointFlags flags) {
this._addPoint(uiPathPoint.create(x: x, y: y, flags: flags));
}
void _addPoint(uiPathPoint point) {
if (this._paths.Count == 0) {
this.addPath();
this.addPoint(0, 0, uiPointFlags.corner);
}
var path = this._paths[this._paths.Count - 1];
if (path.count > 0) {
var pt = this._points[this._points.Count - 1];
if (uiPathUtils.ptEquals(pt.x, pt.y, point.x, point.y, this._distTol)) {
pt.flags |= point.flags;
this._points[this._points.Count - 1] = pt;
return;
}
}
this._points.Add(point);
path.count++;
this._paths[this._paths.Count - 1] = path;
}
public void tessellateBezier(
float x2, float y2,
float x3, float y3, float x4, float y4,
uiPointFlags flags) {
float x1, y1;
if (this._points.Count == 0) {
x1 = 0;
y1 = 0;
}
else {
var pt = this._points[this._points.Count - 1];
x1 = pt.x;
y1 = pt.y;
}
if (x1 == x2 && x1 == x3 && x1 == x4 &&
y1 == y2 && y1 == y3 && y1 == y4) {
return;
}
var points = uiTessellationGenerator.tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, this._tessTol);
D.assert(points.Count > 0);
for (int i = 0; i < points.Count; i++) {
var point = points[i];
if (i == points.Count - 1) {
this._addPoint(uiPathPoint.create(
x: point.x + x1,
y: point.y + y1,
flags: flags
));
}
else {
this._addPoint(uiPathPoint.create(
x: point.x + x1,
y: point.y + y1
));
}
}
}
public void closePath() {
if (this._paths.Count == 0) {
return;
}
var path = this._paths[this._paths.Count - 1];
path.closed = true;
this._paths[this._paths.Count - 1] = path;
}
public void pathWinding(uiPathWinding winding) {
if (this._paths.Count == 0) {
return;
}
var path = this._paths[this._paths.Count - 1];
path.winding = winding;
this._paths[this._paths.Count - 1] = path;
}
public void normalize() {
var points = this._points;
var paths = this._paths;
for (var j = 0; j < paths.Count; j++) {
var path = paths[j];
if (path.count <= 1) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
var p0 = points[ip0];
var p1 = points[ip1];
if (uiPathUtils.ptEquals(p0.x, p0.y, p1.x, p1.y, this._distTol)) {
path.count--;
path.closed = true;
paths[j] = path;
}
if (path.count > 2) {
if (path.winding == uiPathWinding.clockwise) {
uiPathUtils.polyReverse(points, path.first, path.count);
}
}
}
}
uiList<Vector3> _expandFill() {
var points = this._points;
var paths = this._paths;
for (var j = 0; j < paths.Count; j++) {
var path = paths[j];
if (path.count <= 2) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
for (var i = 0; i < path.count; i++) {
var p0 = points[ip0];
var p1 = points[ip1];
p0.dx = p1.x - p0.x; // no need to normalize
p0.dy = p1.y - p0.y;
points[ip0] = p0;
ip0 = ip1++;
}
path.convex = true;
ip0 = path.first + path.count - 1;
ip1 = path.first;
for (var i = 0; i < path.count; i++) {
var p0 = points[ip0];
var p1 = points[ip1];
float cross = p1.dx * p0.dy - p0.dx * p1.dy;
if (cross < 0.0f) {
path.convex = false;
}
ip0 = ip1++;
}
paths[j] = path;
}
var cvertices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
cvertices += path.count;
}
var _vertices = ObjectPool<uiList<Vector3>>.alloc();
_vertices.SetCapacity(cvertices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
path.ifill = _vertices.Count;
for (var j = 0; j < path.count; j++) {
var p = points[path.first + j];
_vertices.Add(new Vector2(p.x, p.y));
}
path.nfill = _vertices.Count - path.ifill;
paths[i] = path;
}
return _vertices;
}
public uiMeshMesh getFillMesh(out bool convex) {
if (this._fillMesh != null) {
convex = this._fillConvex;
return this._fillMesh;
}
var vertices = this._expandFill();
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (path.nfill > 0) {
D.assert(path.nfill >= 2);
cindices += (path.nfill - 2) * 3;
}
}
var indices = ObjectPool<uiList<int>>.alloc();
indices.SetCapacity(cindices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (path.nfill > 0) {
for (var j = 2; j < path.nfill; j++) {
indices.Add(path.ifill);
indices.Add(path.ifill + j);
indices.Add(path.ifill + j - 1);
}
}
}
D.assert(indices.Count == cindices);
var mesh = uiMeshMesh.create(null, vertices, indices);
this._fillMesh = mesh;
this._fillConvex = false;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 2) {
continue;
}
if (this._fillConvex) {
// if more than two paths, convex is false.
this._fillConvex = false;
break;
}
if (!path.convex) {
// if not convex, convex is false.
break;
}
this._fillConvex = true;
}
convex = this._fillConvex;
return this._fillMesh;
}
void _calculateJoins(float w, StrokeJoin lineJoin, float miterLimit) {
float iw = w > 0.0f ? 1.0f / w : 0.0f;
var points = this._points;
var paths = this._paths;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
var ip0 = path.first + path.count - 1;
var ip1 = path.first;
for (var j = 0; j < path.count; j++) {
var p0 = points[ip0];
var p1 = points[ip1];
p0.dx = p1.x - p0.x;
p0.dy = p1.y - p0.y;
p0.len = uiPathUtils.normalize(ref p0.dx, ref p0.dy);
points[ip0] = p0;
ip0 = ip1++;
}
ip0 = path.first + path.count - 1;
ip1 = path.first;
for (var j = 0; j < path.count; j++) {
var p0 = points[ip0];
var p1 = points[ip1];
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
// Calculate extrusions
p1.dmx = (dlx0 + dlx1) * 0.5f;
p1.dmy = (dly0 + dly1) * 0.5f;
float dmr2 = p1.dmx * p1.dmx + p1.dmy * p1.dmy;
if (dmr2 > 0.000001f) {
float scale = 1.0f / dmr2;
if (scale > 600.0f) {
scale = 600.0f;
}
p1.dmx *= scale;
p1.dmy *= scale;
}
// Clear flags, but keep the corner.
p1.flags &= uiPointFlags.corner;
// Keep track of left turns.
float cross = p1.dx * p0.dy - p0.dx * p1.dy;
if (cross > 0.0f) {
p1.flags |= uiPointFlags.left;
}
// Calculate if we should use bevel or miter for inner join.
float limit = Mathf.Max(1.01f, Mathf.Min(p0.len, p1.len) * iw);
if (dmr2 * limit * limit < 1.0f) {
p1.flags |= uiPointFlags.innerBevel;
}
// Check to see if the corner needs to be beveled.
if ((p1.flags & uiPointFlags.corner) != 0) {
if (lineJoin == StrokeJoin.bevel ||
lineJoin == StrokeJoin.round || dmr2 * miterLimit * miterLimit < 1.0f) {
p1.flags |= uiPointFlags.bevel;
}
}
points[ip0] = p0;
points[ip1] = p1;
ip0 = ip1++;
}
}
}
uiList<Vector3> _expandStroke(float w, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) {
this._calculateJoins(w, lineJoin, miterLimit);
int ncap = 0;
if (lineCap == StrokeCap.round || lineJoin == StrokeJoin.round) {
ncap = uiPathUtils.curveDivs(w, Mathf.PI, this._tessTol);
}
var points = this._points;
var paths = this._paths;
var cvertices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
cvertices += path.count * 2;
cvertices += 4;
}
var _vertices = ObjectPool<uiList<Vector3>>.alloc();
_vertices.SetCapacity(cvertices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
path.istroke = _vertices.Count;
int s, e, ip0, ip1;
if (path.closed) {
ip0 = path.first + path.count - 1;
ip1 = path.first;
s = 0;
e = path.count;
}
else {
ip0 = path.first;
ip1 = path.first + 1;
s = 1;
e = path.count - 1;
}
var p0 = points[ip0];
var p1 = points[ip1];
if (!path.closed) {
if (lineCap == StrokeCap.butt) {
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, 0.0f);
}
else if (lineCap == StrokeCap.square) {
_vertices.buttCapStart(p0, p0.dx, p0.dy, w, w);
}
else {
// round
_vertices.roundCapStart(p0, p0.dx, p0.dy, w, ncap);
}
}
for (var j = s; j < e; j++) {
p0 = points[ip0];
p1 = points[ip1];
if ((p1.flags & (uiPointFlags.bevel | uiPointFlags.innerBevel)) != 0) {
if (lineJoin == StrokeJoin.round) {
_vertices.roundJoin(p0, p1, w, w, ncap);
}
else {
_vertices.bevelJoin(p0, p1, w, w);
}
}
else {
_vertices.Add(new Vector2(p1.x + p1.dmx * w, p1.y + p1.dmy * w));
_vertices.Add(new Vector2(p1.x - p1.dmx * w, p1.y - p1.dmy * w));
}
ip0 = ip1++;
}
if (!path.closed) {
p0 = points[ip0];
p1 = points[ip1];
if (lineCap == StrokeCap.butt) {
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, 0.0f);
}
else if (lineCap == StrokeCap.square) {
_vertices.buttCapEnd(p1, p0.dx, p0.dy, w, w);
}
else {
// round
_vertices.roundCapEnd(p1, p0.dx, p0.dy, w, ncap);
}
}
else {
_vertices.Add(_vertices[path.istroke]);
_vertices.Add(_vertices[path.istroke + 1]);
}
path.nstroke = _vertices.Count - path.istroke;
paths[i] = path;
}
return _vertices;
}
public uiMeshMesh getStrokeMesh(float strokeWidth, StrokeCap lineCap, StrokeJoin lineJoin, float miterLimit) {
if (this._strokeMesh != null &&
this._strokeWidth == strokeWidth &&
this._lineCap == lineCap &&
this._lineJoin == lineJoin &&
this._miterLimit == miterLimit) {
return this._strokeMesh;
}
var vertices = this._expandStroke(strokeWidth, lineCap, lineJoin, miterLimit);
var paths = this._paths;
var cindices = 0;
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
if (path.nstroke > 0) {
D.assert(path.nstroke >= 2);
cindices += (path.nstroke - 2) * 3;
}
}
var indices = ObjectPool<uiList<int>>.alloc();
indices.SetCapacity(cindices);
for (var i = 0; i < paths.Count; i++) {
var path = paths[i];
if (path.count <= 1) {
continue;
}
if (path.nstroke > 0) {
for (var j = 2; j < path.nstroke; j++) {
if ((j & 1) == 0) {
indices.Add(path.istroke + j - 1);
indices.Add(path.istroke + j - 2);
indices.Add(path.istroke + j);
}
else {
indices.Add(path.istroke + j - 2);
indices.Add(path.istroke + j - 1);
indices.Add(path.istroke + j);
}
}
}
}
D.assert(indices.Count == cindices);
ObjectPool<uiMeshMesh>.release(this._strokeMesh);
this._strokeMesh = uiMeshMesh.create(null, vertices, indices);
this._strokeWidth = strokeWidth;
this._lineCap = lineCap;
this._lineJoin = lineJoin;
this._miterLimit = miterLimit;
return this._strokeMesh;
}
}
}

323
Runtime/ui/renderer/common/geometry/path/path_utils.cs


using System;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.UIWidgets.ui {
public enum uiPathWinding {
counterClockwise = 1, // which just means the order as the input is.
clockwise = 2, // which just means the reversed order.
}
enum uiPathCommand {
moveTo,
lineTo,
bezierTo,
close,
winding,
}
[Flags]
enum uiPointFlags {
corner = 0x01,
left = 0x02,
bevel = 0x04,
innerBevel = 0x08,
}
struct uiPathPoint {
public float x, y;
public float dx, dy;
public float len;
public float dmx, dmy;
public uiPointFlags flags;
public static uiPathPoint create(float x = 0, float y = 0, float dx = 0, float dy = 0, float len = 0,
float dmx = 0, float dmy = 0,
uiPointFlags flags = uiPointFlags.corner) {
uiPathPoint newPoint = new uiPathPoint();
newPoint.x = x;
newPoint.y = y;
newPoint.dx = dx;
newPoint.dy = dy;
newPoint.len = len;
newPoint.dmx = dmx;
newPoint.dmy = dmy;
newPoint.flags = flags;
return newPoint;
}
}
struct uiPathPath {
public int first;
public int count;
public bool closed;
public int ifill;
public int nfill;
public int istroke;
public int nstroke;
public uiPathWinding winding;
public bool convex;
public static uiPathPath create(int first = 0, int count = 0, bool closed = false, int ifill = 0, int nfill = 0,
int istroke = 0,
int nstroke = 0, uiPathWinding winding = uiPathWinding.counterClockwise, bool convex = false) {
uiPathPath newPath = new uiPathPath();
newPath.first = first;
newPath.count = count;
newPath.closed = closed;
newPath.ifill = ifill;
newPath.nfill = nfill;
newPath.istroke = istroke;
newPath.nstroke = nstroke;
newPath.winding = winding;
newPath.convex = convex;
return newPath;
}
}
static class uiPathUtils {
public static bool ptEquals(float x1, float y1, float x2, float y2, float tol) {
float dx = x2 - x1;
float dy = y2 - y1;
if (dx <= -tol || dx >= tol || dy <= -tol || dy >= tol) {
return false;
}
return dx * dx + dy * dy < tol * tol;
}
public static void polyReverse(List<uiPathPoint> pts, int s, int npts) {
int i = s, j = s + npts - 1;
while (i < j) {
var tmp = pts[i];
pts[i] = pts[j];
pts[j] = tmp;
i++;
j--;
}
}
public static float normalize(ref float x, ref float y) {
float d = Mathf.Sqrt(x * x + y * y);
if (d > 1e-6f) {
float id = 1.0f / d;
x *= id;
y *= id;
}
return d;
}
public static void buttCapStart(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, float d) {
float px = p.x - dx * d;
float py = p.y - dy * d;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void buttCapEnd(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, float d) {
float px = p.x + dx * d;
float py = p.y + dy * d;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void roundCapStart(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, int ncap) {
float px = p.x;
float py = p.y;
float dlx = dy;
float dly = -dx;
for (var i = 0; i < ncap; i++) {
float a = (float) i / (ncap - 1) * Mathf.PI;
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w;
dst.Add(new Vector2(px - dlx * ax - dx * ay, py - dly * ax - dy * ay));
dst.Add(new Vector2(px, py));
}
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
}
public static void roundCapEnd(this uiList<Vector3> dst, uiPathPoint p,
float dx, float dy, float w, int ncap) {
float px = p.x;
float py = p.y;
float dlx = dy;
float dly = -dx;
dst.Add(new Vector2(px + dlx * w, py + dly * w));
dst.Add(new Vector2(px - dlx * w, py - dly * w));
for (var i = 0; i < ncap; i++) {
float a = (float) i / (ncap - 1) * Mathf.PI;
float ax = Mathf.Cos(a) * w, ay = Mathf.Sin(a) * w;
dst.Add(new Vector2(px, py));
dst.Add(new Vector2(px - dlx * ax + dx * ay, py - dly * ax + dy * ay));
}
}
public static void chooseBevel(bool bevel, uiPathPoint p0, uiPathPoint p1, float w,
out float x0, out float y0, out float x1, out float y1) {
if (bevel) {
x0 = p1.x + p0.dy * w;
y0 = p1.y - p0.dx * w;
x1 = p1.x + p1.dy * w;
y1 = p1.y - p1.dx * w;
}
else {
x0 = p1.x + p1.dmx * w;
y0 = p1.y + p1.dmy * w;
x1 = p1.x + p1.dmx * w;
y1 = p1.y + p1.dmy * w;
}
}
public static int curveDivs(float r, float arc, float tol) {
float da = Mathf.Acos(r / (r + tol)) * 2.0f;
return Mathf.Max(2, Mathf.CeilToInt(arc / da));
}
public static void roundJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1,
float lw, float rw, int ncap) {
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
if ((p1.flags & uiPointFlags.left) != 0) {
float lx0, ly0, lx1, ly1;
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw,
out lx0, out ly0, out lx1, out ly1);
float a0 = Mathf.Atan2(-dly0, -dlx0);
float a1 = Mathf.Atan2(-dly1, -dlx1);
if (a1 > a0) {
a1 -= Mathf.PI * 2;
}
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
var n = Mathf.CeilToInt((a0 - a1) / Mathf.PI * ncap).clamp(2, ncap);
for (var i = 0; i < n; i++) {
float u = (float) i / (n - 1);
float a = a0 + u * (a1 - a0);
float rx = p1.x + Mathf.Cos(a) * rw;
float ry = p1.y + Mathf.Sin(a) * rw;
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(rx, ry));
}
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
float rx0, ry0, rx1, ry1;
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw,
out rx0, out ry0, out rx1, out ry1);
float a0 = Mathf.Atan2(dly0, dlx0);
float a1 = Mathf.Atan2(dly1, dlx1);
if (a1 < a0) {
a1 += Mathf.PI * 2;
}
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
var n = Mathf.CeilToInt((a1 - a0) / Mathf.PI * ncap).clamp(2, ncap);
for (var i = 0; i < n; i++) {
float u = (float) i / (n - 1);
float a = a0 + u * (a1 - a0);
float lx = p1.x + Mathf.Cos(a) * lw;
float ly = p1.y + Mathf.Sin(a) * lw;
dst.Add(new Vector2(lx, ly));
dst.Add(new Vector2(p1.x, p1.y));
}
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
}
public static void bevelJoin(this uiList<Vector3> dst, uiPathPoint p0, uiPathPoint p1,
float lw, float rw) {
float rx0, ry0, rx1, ry1;
float lx0, ly0, lx1, ly1;
float dlx0 = p0.dy;
float dly0 = -p0.dx;
float dlx1 = p1.dy;
float dly1 = -p1.dx;
if ((p1.flags & uiPointFlags.left) != 0) {
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, lw,
out lx0, out ly0, out lx1, out ly1);
dst.Add(new Vector2 {x = lx0, y = ly0});
dst.Add(new Vector2 {x = p1.x - dlx0 * rw, y = p1.y - dly0 * rw});
if ((p1.flags & uiPointFlags.bevel) != 0) {
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
rx0 = p1.x - p1.dmx * rw;
ry0 = p1.y - p1.dmy * rw;
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(p1.x - dlx0 * rw, p1.y - dly0 * rw));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
dst.Add(new Vector2(lx1, ly1));
dst.Add(new Vector2(p1.x - dlx1 * rw, p1.y - dly1 * rw));
}
else {
chooseBevel((p1.flags & uiPointFlags.innerBevel) != 0, p0, p1, -rw,
out rx0, out ry0, out rx1, out ry1);
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
if ((p1.flags & uiPointFlags.bevel) != 0) {
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(rx0, ry0));
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
else {
lx0 = p1.x + p1.dmx * lw;
ly0 = p1.y + p1.dmy * lw;
dst.Add(new Vector2(p1.x + dlx0 * lw, p1.y + dly0 * lw));
dst.Add(new Vector2(p1.x, p1.y));
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(lx0, ly0));
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(p1.x, p1.y));
}
dst.Add(new Vector2(p1.x + dlx1 * lw, p1.y + dly1 * lw));
dst.Add(new Vector2(rx1, ry1));
}
}
}
}

261
Runtime/ui/renderer/common/geometry/path/tessellation_generator.cs


using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace Unity.UIWidgets.ui {
class uiTessellationKey : PoolObject, IEquatable<uiTessellationKey> {
public float x2;
public float y2;
public float x3;
public float y3;
public float x4;
public float y4;
public float tessTol;
public static uiTessellationKey create(float x1, float y1, float x2, float y2, float x3, float y3, float x4,
float y4,
float tessTol) {
var newKey = ObjectPool<uiTessellationKey>.alloc();
newKey.x2 = x2 - x1;
newKey.y2 = y2 - y1;
newKey.x3 = x3 - x1;
newKey.y3 = y3 - y1;
newKey.x4 = x4 - x1;
newKey.y4 = y4 - y1;
newKey.tessTol = tessTol;
return newKey;
}
public uiTessellationKey() {
}
public bool Equals(uiTessellationKey other) {
if (ReferenceEquals(null, other)) {
return false;
}
if (ReferenceEquals(this, other)) {
return true;
}
return this.x2 == other.x2 && this.y2 == other.y2 && this.x3 == other.x3 &&
this.y3 == other.y3 && this.x4 == other.x4 && this.y4 == other.y4 &&
this.tessTol == other.tessTol;
}
public override bool Equals(object obj) {
if (ReferenceEquals(null, obj)) {
return false;
}
if (ReferenceEquals(this, obj)) {
return true;
}
if (obj.GetType() != this.GetType()) {
return false;
}
return this.Equals((uiTessellationKey) obj);
}
public override unsafe int GetHashCode() {
unchecked {
var hashCode = 0;
float x = this.x2;
hashCode ^= *(int*) &x;
x = this.y2;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.x3;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.y3;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.x4;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.y4;
hashCode = (hashCode * 13) ^ *(int*) &x;
x = this.tessTol;
hashCode = (hashCode * 13) ^ *(int*) &x;
return hashCode;
}
}
public static bool operator ==(uiTessellationKey left, uiTessellationKey right) {
return Equals(left, right);
}
public static bool operator !=(uiTessellationKey left, uiTessellationKey right) {
return !Equals(left, right);
}
public override string ToString() {
return $"uiTessellationKey(" +
$"x2: {this.x2}, " +
$"y2: {this.y2}, " +
$"x3: {this.x3}, " +
$"y3: {this.y3}, " +
$"x4: {this.x4}, " +
$"y4: {this.y4}, " +
$"tessTol: {this.tessTol})";
}
}
class uiTessellationInfo : PoolObject {
public uiTessellationKey key;
public uiList<Vector2> points;
long _timeToLive;
public static uiTessellationInfo create(uiTessellationKey key, uiList<Vector2> points, int timeToLive = 5) {
var newInfo = ObjectPool<uiTessellationInfo>.alloc();
newInfo.points = points;
newInfo.key = key;
newInfo.touch(timeToLive);
return newInfo;
}
public uiTessellationInfo() {
}
public override void clear() {
ObjectPool<uiList<Vector2>>.release(this.points);
}
public long timeToLive {
get { return this._timeToLive; }
}
public void touch(long timeTolive = 5) {
this._timeToLive = timeTolive + TextBlobMesh.frameCount;
}
}
static class uiTessellationGenerator {
static readonly Dictionary<uiTessellationKey, uiTessellationInfo> _tessellations =
new Dictionary<uiTessellationKey, uiTessellationInfo>();
static long _frameCount = 0;
public static long frameCount {
get { return _frameCount; }
}
public static int tessellationCount {
get { return _tessellations.Count; }
}
public static void tickNextFrame() {
_frameCount++;
var keysToRemove = _tessellations.Values.Where(info => info.timeToLive < _frameCount)
.Select(info => info.key).ToList();
foreach (var key in keysToRemove) {
ObjectPool<uiTessellationKey>.release(key);
ObjectPool<uiTessellationInfo>.release(_tessellations[key]);
_tessellations.Remove(key);
}
}
public static uiList<Vector2> tessellateBezier(float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4, float tessTol) {
var key = uiTessellationKey.create(x1, y1, x2, y2, x3, y3, x4, y4, tessTol);
_tessellations.TryGetValue(key, out var uiTessellationInfo);
if (uiTessellationInfo != null) {
ObjectPool<uiTessellationKey>.release(key);
uiTessellationInfo.touch();
return uiTessellationInfo.points;
}
var points = _tessellateBezier(x1, y1, x2, y2, x3, y3, x4, y4, tessTol);
_tessellations[key] = uiTessellationInfo.create(key, points);
return points;
}
struct _StackData {
public float x1;
public float y1;
public float x2;
public float y2;
public float x3;
public float y3;
public float x4;
public float y4;
public int level;
}
static readonly Stack<_StackData> _stack = new Stack<_StackData>();
static uiList<Vector2> _tessellateBezier(
float x1, float y1, float x2, float y2,
float x3, float y3, float x4, float y4,
float tessTol) {
x2 = x2 - x1;
y2 = y2 - y1;
x3 = x3 - x1;
y3 = y3 - y1;
x4 = x4 - x1;
y4 = y4 - y1;
var points = ObjectPool<uiList<Vector2>>.alloc();
_stack.Clear();
_stack.Push(new _StackData {
x1 = 0, y1 = 0, x2 = x2, y2 = y2, x3 = x3, y3 = y3, x4 = x4, y4 = y4, level = 0,
});
while (_stack.Count > 0) {
var stackData = _stack.Pop();
x1 = stackData.x1;
y1 = stackData.y1;
x2 = stackData.x2;
y2 = stackData.y2;
x3 = stackData.x3;
y3 = stackData.y3;
x4 = stackData.x4;
y4 = stackData.y4;
int level = stackData.level;
float dx = x4 - x1;
float dy = y4 - y1;
float d2 = Mathf.Abs((x2 - x4) * dy - (y2 - y4) * dx);
float d3 = Mathf.Abs((x3 - x4) * dy - (y3 - y4) * dx);
if ((d2 + d3) * (d2 + d3) <= tessTol * (dx * dx + dy * dy)) {
points.Add(new Vector2(x4, y4));
continue;
}
float x12 = (x1 + x2) * 0.5f;
float y12 = (y1 + y2) * 0.5f;
float x23 = (x2 + x3) * 0.5f;
float y23 = (y2 + y3) * 0.5f;
float x34 = (x3 + x4) * 0.5f;
float y34 = (y3 + y4) * 0.5f;
float x123 = (x12 + x23) * 0.5f;
float y123 = (y12 + y23) * 0.5f;
float x234 = (x23 + x34) * 0.5f;
float y234 = (y23 + y34) * 0.5f;
float x1234 = (x123 + x234) * 0.5f;
float y1234 = (y123 + y234) * 0.5f;
if (level < 10) {
_stack.Push(new _StackData {
x1 = x1234, y1 = y1234, x2 = x234, y2 = y234, x3 = x34, y3 = y34, x4 = x4, y4 = y4,
level = level + 1,
});
_stack.Push(new _StackData {
x1 = x1, y1 = y1, x2 = x12, y2 = y12, x3 = x123, y3 = y123, x4 = x1234, y4 = y1234,
level = level + 1,
});
}
}
return points;
}
}
}

227
Runtime/ui/renderer/common/geometry/rect.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public struct uiRect {
public uiRect(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 bool isEmpty {
get { return this.left >= this.right || this.top >= this.bottom; }
}
public float width {
get { return this.right - this.left; }
}
public float height {
get { return this.bottom - this.top; }
}
public uiOffset topLeft {
get { return new uiOffset(this.left, this.top); }
}
public uiOffset topCenter {
get { return new uiOffset(this.left + this.width / 2.0f, this.top); }
}
public uiOffset topRight {
get { return new uiOffset(this.right, this.top); }
}
public uiOffset centerLeft {
get { return new uiOffset(this.left, this.top + this.height / 2.0f); }
}
public uiOffset center {
get { return new uiOffset(this.left + this.width / 2.0f, this.top + this.height / 2.0f); }
}
public uiOffset centerRight {
get { return new uiOffset(this.right, this.bottom); }
}
public uiOffset bottomLeft {
get { return new uiOffset(this.left, this.bottom); }
}
public uiOffset bottomCenter {
get { return new uiOffset(this.left + this.width / 2.0f, this.bottom); }
}
public uiOffset bottomRight {
get { return new uiOffset(this.right, this.bottom); }
}
public uiRect shift(uiOffset offset) {
return uiRectHelper.fromLTRB(this.left + offset.dx, this.top + offset.dy, this.right + offset.dx,
this.bottom + offset.dy);
}
public uiRect intersect(uiRect other) {
return uiRectHelper.fromLTRB(
Mathf.Max(this.left, other.left),
Mathf.Max(this.top, other.top),
Mathf.Min(this.right, other.right),
Mathf.Min(this.bottom, other.bottom)
);
}
public uiRect expandToInclude(uiRect? other) {
if (this.isEmpty) {
return other.Value;
}
if (other == null || other.Value.isEmpty) {
return this;
}
return uiRectHelper.fromLTRB(
Mathf.Min(this.left, other.Value.left),
Mathf.Min(this.top, other.Value.top),
Mathf.Max(this.right, other.Value.right),
Mathf.Max(this.bottom, other.Value.bottom)
);
}
}
public static class uiRectHelper {
public static uiRect fromRect(Rect rect) {
return new uiRect(rect.left, rect.top, rect.right, rect.bottom);
}
public static uiRect fromLTRB(float left, float top, float right, float bottom) {
return new uiRect(left, top, right, bottom);
}
public static uiRect fromLTWH(float left, float top, float width, float height) {
return new uiRect(left, top, left + width, top + height);
}
public static readonly uiRect zero = new uiRect(0, 0, 0, 0);
public static readonly uiRect one = new uiRect(0, 0, 1, 1);
public static bool equals(uiRect? a, uiRect? b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
var aval = a.Value;
var bval = b.Value;
return aval.left == bval.left && aval.right == bval.right && aval.top == bval.top &&
aval.bottom == bval.bottom;
}
public static uiRect scale(uiRect a, float scaleX, float? scaleY = null) {
scaleY = scaleY ?? scaleX;
return fromLTRB(
a.left * scaleX, a.top * scaleY.Value,
a.right * scaleX, a.bottom * scaleY.Value);
}
public static uiRect inflate(uiRect a, float delta) {
return fromLTRB(a.left - delta, a.top - delta, a.right + delta, a.bottom + delta);
}
public static uiRect deflate(uiRect a, float delta) {
return inflate(a, -delta);
}
public static uiRect intersect(uiRect a, uiRect other) {
return fromLTRB(
Mathf.Max(a.left, other.left),
Mathf.Max(a.top, other.top),
Mathf.Min(a.right, other.right),
Mathf.Min(a.bottom, other.bottom)
);
}
public static uiRect round(uiRect a) {
return fromLTRB(
Mathf.Round(a.left), Mathf.Round(a.top),
Mathf.Round(a.right), Mathf.Round(a.bottom));
}
public static uiRect roundOut(uiRect a) {
return fromLTRB(
Mathf.Floor(a.left), Mathf.Floor(a.top),
Mathf.Ceil(a.right), Mathf.Ceil(a.bottom));
}
public static uiRect roundOut(uiRect a, float devicePixelRatio) {
return fromLTRB(
Mathf.Floor(a.left * devicePixelRatio) / devicePixelRatio,
Mathf.Floor(a.top * devicePixelRatio) / devicePixelRatio,
Mathf.Ceil(a.right * devicePixelRatio) / devicePixelRatio,
Mathf.Ceil(a.bottom * devicePixelRatio) / devicePixelRatio);
}
public static uiRect roundIn(uiRect a) {
return fromLTRB(
Mathf.Ceil(a.left), Mathf.Ceil(a.top),
Mathf.Floor(a.right), Mathf.Floor(a.bottom));
}
public static uiRect normalize(uiRect a) {
if (a.left <= a.right && a.top <= a.bottom) {
return a;
}
return fromLTRB(
Mathf.Min(a.left, a.right),
Mathf.Min(a.top, a.bottom),
Mathf.Max(a.left, a.right),
Mathf.Max(a.top, a.bottom)
);
}
public static uiOffset[] toQuad(uiRect a) {
uiOffset[] dst = new uiOffset[4];
dst[0] = new uiOffset(a.left, a.top);
dst[1] = new uiOffset(a.right, a.top);
dst[2] = new uiOffset(a.right, a.bottom);
dst[3] = new uiOffset(a.left, a.bottom);
return dst;
}
public static bool contains(uiRect a, uiOffset offset) {
return offset.dx >= a.left && offset.dx < a.right && offset.dy >= a.top && offset.dy < a.bottom;
}
public static bool contains(uiRect a, uiRect rect) {
return contains(a, rect.topLeft) && contains(a, rect.bottomRight);
}
public static bool overlaps(uiRect a, uiRect other) {
if (a.right <= other.left || other.right <= a.left) {
return false;
}
if (a.bottom <= other.top || other.bottom <= a.top) {
return false;
}
return true;
}
public static UnityEngine.Rect toRect(uiRect rect) {
return new UnityEngine.Rect(rect.left, rect.top, rect.width, rect.height);
}
}
}

171
Runtime/ui/renderer/common/paint.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
public struct uiMaskFilter {
uiMaskFilter(BlurStyle style, float sigma) {
this.style = style;
this.sigma = sigma;
}
public static uiMaskFilter blur(BlurStyle style, float sigma) {
return new uiMaskFilter(style, sigma);
}
public readonly BlurStyle style;
public readonly float sigma;
}
public struct uiColorFilter {
uiColorFilter(uiColor color, BlendMode blendMode) {
this.color = color;
this.blendMode = blendMode;
}
public static uiColorFilter mode(uiColor color, BlendMode blendMode) {
return new uiColorFilter(color, blendMode);
}
public readonly uiColor color;
public readonly BlendMode blendMode;
}
public interface uiImageFilter {
}
public static class uiImageFilterHelper {
public static uiImageFilter blur(float sigmaX = 0.0f, float sigmaY = 0.0f) {
return new _uiBlurImageFilter(sigmaX, sigmaY);
}
public static uiImageFilter matrix(uiMatrix3 transform, FilterMode filterMode = FilterMode.Bilinear) {
return new _uiMatrixImageFilter(transform, filterMode);
}
}
struct _uiBlurImageFilter : uiImageFilter {
public _uiBlurImageFilter(float sigmaX, float sigmaY) {
this.sigmaX = sigmaX;
this.sigmaY = sigmaY;
}
public readonly float sigmaX;
public readonly float sigmaY;
}
struct _uiMatrixImageFilter : uiImageFilter {
public _uiMatrixImageFilter(uiMatrix3 transform, FilterMode filterMode) {
this.transform = transform;
this.filterMode = filterMode;
}
public readonly uiMatrix3 transform;
public readonly FilterMode filterMode;
}
public struct uiPaint {
static readonly uiColor _kColorDefault = new uiColor(0xFFFFFFFF);
public uiColor color;
public BlendMode blendMode;
public PaintingStyle style;
public float strokeWidth;
public StrokeCap strokeCap;
public StrokeJoin strokeJoin;
public float strokeMiterLimit;
public FilterMode filterMode;
public uiColorFilter? colorFilter;
public uiMaskFilter? maskFilter;
public uiImageFilter backdrop;
public PaintShader shader;
public bool invertColors;
public uiPaint(
uiColor? color = null,
BlendMode blendMode = BlendMode.srcOver,
PaintingStyle style = PaintingStyle.fill,
float strokeWidth = 0f,
StrokeCap strokeCap = StrokeCap.butt,
StrokeJoin strokeJoin = StrokeJoin.miter,
float strokeMiterLimit = 4.0f,
FilterMode filterMode = FilterMode.Bilinear,
uiColorFilter? colorFilter = null,
uiMaskFilter? maskFilter = null,
uiImageFilter backdrop = null,
PaintShader shader = null,
bool invertColors = false
) {
this.color = color ?? _kColorDefault;
this.blendMode = blendMode;
this.style = style;
this.strokeWidth = strokeWidth;
this.strokeCap = strokeCap;
this.strokeJoin = strokeJoin;
this.strokeMiterLimit = strokeMiterLimit;
this.filterMode = filterMode;
this.colorFilter = colorFilter;
this.maskFilter = maskFilter;
this.backdrop = backdrop;
this.shader = shader;
this.invertColors = invertColors;
}
public uiPaint(uiPaint paint) {
this.color = paint.color;
this.blendMode = paint.blendMode;
this.style = paint.style;
this.strokeWidth = paint.strokeWidth;
this.strokeCap = paint.strokeCap;
this.strokeJoin = paint.strokeJoin;
this.strokeMiterLimit = paint.strokeMiterLimit;
this.filterMode = paint.filterMode;
this.colorFilter = paint.colorFilter;
this.maskFilter = paint.maskFilter;
this.backdrop = paint.backdrop;
this.shader = paint.shader;
this.invertColors = paint.invertColors;
}
public static uiPaint shapeOnly(uiPaint paint) {
return new uiPaint(
style: paint.style,
strokeWidth: paint.strokeWidth,
strokeCap: paint.strokeCap,
strokeJoin: paint.strokeJoin,
strokeMiterLimit: paint.strokeMiterLimit
);
}
public static uiPaint fromPaint(Paint paint) {
uiImageFilter filter = null;
if (paint.backdrop is _BlurImageFilter) {
var blurFilter = (_BlurImageFilter) paint.backdrop;
filter = uiImageFilterHelper.blur(blurFilter.sigmaX, blurFilter.sigmaY);
}
else if (paint.backdrop is _MatrixImageFilter) {
var matrixFilter = (_MatrixImageFilter) paint.backdrop;
filter = uiImageFilterHelper.matrix(uiMatrix3.fromMatrix3(matrixFilter.transform),
matrixFilter.filterMode);
}
return new uiPaint(
color: paint.color == null ? (uiColor?) null : uiColor.fromColor(paint.color),
blendMode: paint.blendMode,
style: paint.style,
strokeWidth: paint.strokeWidth,
strokeCap: paint.strokeCap,
strokeJoin: paint.strokeJoin,
strokeMiterLimit: paint.strokeMiterLimit,
filterMode: paint.filterMode,
colorFilter: paint.colorFilter == null
? (uiColorFilter?) null
: uiColorFilter.mode(uiColor.fromColor(paint.colorFilter.color), paint.colorFilter.blendMode),
maskFilter: paint.maskFilter == null
? (uiMaskFilter?) null
: uiMaskFilter.blur(paint.maskFilter.style, paint.maskFilter.sigma),
backdrop: filter,
shader: paint.shader,
invertColors: paint.invertColors
);
}
}
}

11
Runtime/ui/renderer/common/paint.cs.meta


fileFormatVersion: 2
guid: 9bde84e37c33148879131974b64a62aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

322
Runtime/ui/renderer/common/picture.cs


using System;
using System.Collections.Generic;
using Unity.UIWidgets.foundation;
namespace Unity.UIWidgets.ui {
public class uiPicture : PoolObject {
public uiPicture() {
}
public static uiPicture create(List<uiDrawCmd> drawCmds, uiRect paintBounds) {
var picture = ObjectPool<uiPicture>.alloc();
picture.drawCmds = drawCmds;
picture.paintBounds = paintBounds;
return picture;
}
public List<uiDrawCmd> drawCmds;
public uiRect paintBounds;
public override void clear() {
//the recorder will dispose the draw commands
this.drawCmds = null;
}
}
public class uiPictureRecorder {
readonly List<uiDrawCmd> _drawCmds = new List<uiDrawCmd>(128);
readonly List<uiCanvasState> _states = new List<uiCanvasState>(32);
public uiPictureRecorder() {
this.reset();
}
uiCanvasState _getState() {
D.assert(this._states.Count > 0);
return this._states[this._states.Count - 1];
}
void _setState(uiCanvasState state) {
this._states[this._states.Count - 1] = state;
}
public uiMatrix3 getTotalMatrix() {
return this._getState().xform;
}
public void reset() {
foreach (var drawCmd in this._drawCmds) {
drawCmd.release();
}
this._drawCmds.Clear();
this._states.Clear();
this._states.Add(new uiCanvasState {
xform = uiMatrix3.I(),
scissor = null,
saveLayer = false,
layerOffset = null,
paintBounds = uiRectHelper.zero
});
}
public uiPicture endRecording() {
if (this._states.Count > 1) {
throw new Exception("unmatched save/restore commands");
}
var state = this._getState();
return uiPicture.create(this._drawCmds, state.paintBounds);
}
public void addDrawCmd(uiDrawCmd drawCmd) {
this._drawCmds.Add(drawCmd);
switch (drawCmd) {
case uiDrawSave _:
this._states.Add(this._getState().copy());
break;
case uiDrawSaveLayer cmd: {
this._states.Add(new uiCanvasState {
xform = uiMatrix3.I(),
scissor = cmd.rect.Value.shift(-cmd.rect.Value.topLeft),
saveLayer = true,
layerOffset = cmd.rect.Value.topLeft,
paintBounds = uiRectHelper.zero
});
break;
}
case uiDrawRestore _: {
var stateToRestore = this._getState();
this._states.RemoveAt(this._states.Count - 1);
var state = this._getState();
if (!stateToRestore.saveLayer) {
state.paintBounds = stateToRestore.paintBounds;
}
else {
var paintBounds = stateToRestore.paintBounds.shift(stateToRestore.layerOffset.Value);
paintBounds = state.xform.mapRect(paintBounds);
this._addPaintBounds(paintBounds);
}
this._setState(state);
break;
}
case uiDrawTranslate cmd: {
var state = this._getState();
state.xform = new uiMatrix3(state.xform);
state.xform.preTranslate(cmd.dx, cmd.dy);
this._setState(state);
break;
}
case uiDrawScale cmd: {
var state = this._getState();
state.xform = new uiMatrix3(state.xform);
state.xform.preScale(cmd.sx, (cmd.sy ?? cmd.sx));
this._setState(state);
break;
}
case uiDrawRotate cmd: {
var state = this._getState();
state.xform = new uiMatrix3(state.xform);
if (cmd.offset == null) {
state.xform.preRotate(cmd.radians);
}
else {
state.xform.preRotate(cmd.radians,
cmd.offset.Value.dx,
cmd.offset.Value.dy);
}
this._setState(state);
break;
}
case uiDrawSkew cmd: {
var state = this._getState();
state.xform = new uiMatrix3(state.xform);
state.xform.preSkew(cmd.sx, cmd.sy);
this._setState(state);
break;
}
case uiDrawConcat cmd: {
var state = this._getState();
state.xform = new uiMatrix3(state.xform);
state.xform.preConcat(cmd.matrix.Value);
this._setState(state);
break;
}
case uiDrawResetMatrix _: {
var state = this._getState();
state.xform = uiMatrix3.I();
this._setState(state);
break;
}
case uiDrawSetMatrix cmd: {
var state = this._getState();
state.xform = new uiMatrix3(cmd.matrix.Value);
this._setState(state);
break;
}
case uiDrawClipRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.rect.Value);
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect);
this._setState(state);
break;
}
case uiDrawClipRRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(uiRectHelper.fromRect(cmd.rrect.outerRect));
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect);
this._setState(state);
break;
}
case uiDrawClipPath cmd: {
var state = this._getState();
var scale = uiXformUtils.getScale(state.xform);
var rectPathCache = cmd.path.flatten(
scale * Window.instance.devicePixelRatio);
var rectMesh = rectPathCache.getFillMesh(out _);
var transformedMesh = rectMesh.transform(state.xform);
var rect = transformedMesh.bounds;
state.scissor = state.scissor == null ? rect : state.scissor.Value.intersect(rect);
this._setState(state);
ObjectPool<uiMeshMesh>.release(transformedMesh);
break;
}
case uiDrawPath cmd: {
var state = this._getState();
var scale = uiXformUtils.getScale(state.xform);
var path = cmd.path;
var paint = cmd.paint;
var devicePixelRatio = Window.instance.devicePixelRatio;
uiMeshMesh mesh;
if (paint.style == PaintingStyle.fill) {
var cache = path.flatten(scale * devicePixelRatio);
var fillMesh = cache.getFillMesh(out _);
mesh = fillMesh.transform(state.xform);
}
else {
float strokeWidth = (paint.strokeWidth * scale).clamp(0, 200.0f);
float fringeWidth = 1 / devicePixelRatio;
if (strokeWidth < fringeWidth) {
strokeWidth = fringeWidth;
}
var cache = path.flatten(scale * devicePixelRatio);
var strokenMesh = cache.getStrokeMesh(
strokeWidth / scale * 0.5f,
paint.strokeCap,
paint.strokeJoin,
paint.strokeMiterLimit);
mesh = strokenMesh.transform(state.xform);
}
if (paint.maskFilter != null && paint.maskFilter.Value.sigma != 0) {
float sigma = scale * paint.maskFilter.Value.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(uiRectHelper.inflate(mesh.bounds, sigma3));
}
else {
this._addPaintBounds(mesh.bounds);
}
ObjectPool<uiMeshMesh>.release(mesh);
break;
}
case uiDrawImage cmd: {
var state = this._getState();
var rect = uiRectHelper.fromLTWH(cmd.offset.Value.dx, cmd.offset.Value.dy,
cmd.image.width, cmd.image.height);
rect = state.xform.mapRect(rect);
this._addPaintBounds(rect);
break;
}
case uiDrawImageRect cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.dst.Value);
this._addPaintBounds(rect);
break;
}
case uiDrawImageNine cmd: {
var state = this._getState();
var rect = state.xform.mapRect(cmd.dst.Value);
this._addPaintBounds(rect);
break;
}
case uiDrawPicture cmd: {
var state = this._getState();
var rect = state.xform.mapRect(uiRectHelper.fromRect(cmd.picture.paintBounds));
this._addPaintBounds(rect);
break;
}
case uiDrawTextBlob cmd: {
var state = this._getState();
var scale = uiXformUtils.getScale(state.xform);
var rect = uiRectHelper.fromRect(cmd.textBlob.boundsInText).shift(cmd.offset.Value);
rect = state.xform.mapRect(rect);
var paint = cmd.paint;
if (paint.maskFilter != null && paint.maskFilter.Value.sigma != 0) {
float sigma = scale * paint.maskFilter.Value.sigma;
float sigma3 = 3 * sigma;
this._addPaintBounds(uiRectHelper.inflate(rect, sigma3));
}
else {
this._addPaintBounds(rect);
}
break;
}
default:
throw new Exception("unknown drawCmd: " + drawCmd);
}
}
void _addPaintBounds(uiRect? paintBounds) {
var state = this._getState();
if (state.scissor != null) {
paintBounds = paintBounds.Value.intersect(state.scissor.Value);
}
if (paintBounds == null || paintBounds.Value.isEmpty) {
return;
}
if (state.paintBounds.isEmpty) {
state.paintBounds = paintBounds.Value;
}
else {
state.paintBounds = state.paintBounds.expandToInclude(paintBounds.Value);
}
this._setState(state);
}
struct uiCanvasState {
public uiMatrix3 xform;
public uiRect? scissor;
public bool saveLayer;
public uiOffset? layerOffset;
public uiRect paintBounds;
public uiCanvasState copy() {
return new uiCanvasState {
xform = this.xform,
scissor = this.scissor,
saveLayer = false,
layerOffset = null,
paintBounds = this.paintBounds
};
}
}
}
}

11
Runtime/ui/renderer/common/picture.cs.meta


fileFormatVersion: 2
guid: cb2a188869ac14f84b90cf8b06a0f048
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

53
Runtime/ui/renderer/common/utils.cs


using UnityEngine;
namespace Unity.UIWidgets.ui {
static class uiXformUtils {
public static float getScaleX(uiMatrix3 matrix) {
// ignore perspective parameters for now.
if (matrix.isIdentity()) {
return 1.0f;
}
if (matrix.getSkewY() == 0) {
return matrix.getScaleX();
}
var x = matrix.getScaleX();
var y = matrix.getSkewY();
return Mathf.Sqrt(x * x + y * y);
}
public static float getScaleY(uiMatrix3 matrix) {
// ignore perspective parameters for now.
if (matrix.isIdentity()) {
return 1.0f;
}
if (matrix.getSkewX() == 0) {
return matrix.getScaleY();
}
var x = matrix.getSkewX();
var y = matrix.getScaleY();
return Mathf.Sqrt(x * x + y * y);
}
public static float getScale(uiMatrix3 matrix) {
var scaleX = getScaleX(matrix);
var scaleY = getScaleY(matrix);
if (scaleX == 1.0) {
return scaleY;
}
if (scaleY == 1.0) {
return scaleX;
}
// geometric mean of len0 and len1.
return Mathf.Sqrt(scaleX * scaleY);
}
}
}

11
Runtime/ui/renderer/common/utils.cs.meta


fileFormatVersion: 2
guid: fb644db0d0fbd48208a50a3321bc5840
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

8
Runtime/ui/renderer/compositeCanvas.meta


fileFormatVersion: 2
guid: 6f7a64e74fe2b445abd45004603580e5
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

11
Runtime/ui/renderer/compositeCanvas/compositing.cs.meta


fileFormatVersion: 2
guid: ce66bd4727b6e47d28bc5830b4af948a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存