您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

205 行
7.6 KiB

using System;
using System.Collections.Generic;
using UIWidgets.painting;
using UnityEngine;
namespace UIWidgets.ui {
public class Picture {
public Picture(List<DrawCmd> drawCmds, Rect paintBounds) {
this.drawCmds = drawCmds;
this.paintBounds = paintBounds;
}
public readonly List<DrawCmd> drawCmds;
public readonly Rect paintBounds;
}
public class PictureRecorder {
private readonly List<DrawCmd> _drawCmds = new List<DrawCmd>();
private Matrix4x4 _transform;
private Rect _clipRect;
private bool _isInLayer;
private Rect _paintBounds;
private Stack<CanvasRec> _stack;
public PictureRecorder() {
this._transform = Matrix4x4.identity;
this._clipRect = null;
this._isInLayer = false;
this._paintBounds = null;
}
private Stack<CanvasRec> stack {
get { return this._stack ?? (this._stack = new Stack<CanvasRec>()); }
}
public Picture endRecording() {
if (this._stack != null && this._stack.Count > 0) {
throw new Exception("unmatched save/restore commands");
}
return new Picture(this._drawCmds, this._paintBounds);
}
public void addDrawCmd(DrawCmd drawCmd) {
this._drawCmds.Add(drawCmd);
if (drawCmd is DrawPloygon4) {
var drawPloygon4 = (DrawPloygon4) drawCmd;
if (drawPloygon4.paint.color.alpha > 0) {
this.addPaintBounds(drawPloygon4.points);
}
} else if (drawCmd is DrawRect) {
var drawRect = (DrawRect) drawCmd;
if (drawRect.paint.color.alpha > 0) {
this.addPaintBounds(drawRect.rect);
}
} else if (drawCmd is DrawRectShadow) {
var drawRectShadow = (DrawRectShadow) drawCmd;
if (drawRectShadow.paint.color.alpha > 0) {
this.addPaintBounds(drawRectShadow.rect);
}
} else if (drawCmd is DrawPicture) {
var drawPicture = (DrawPicture) drawCmd;
this.addPaintBounds(drawPicture.picture.paintBounds);
} else if (drawCmd is DrawConcat) {
this._transform = ((DrawConcat) drawCmd).transform * this._transform;
} else if (drawCmd is DrawSave) {
this.stack.Push(new CanvasRec(
this._transform,
this._clipRect,
this._isInLayer,
null
));
} else if (drawCmd is DrawLine)
{
var drawLine = (DrawLine) drawCmd;
Offset vect = drawLine.to - drawLine.from;
var distance = vect.distance;
if (distance > 0)
{
var halfWidth = drawLine.paint.strokeWidth * 0.5;
var diff = vect / distance * halfWidth;
diff = new Offset(diff.dy, -diff.dx);
var offsets = new Offset[]
{
drawLine.from + diff,
drawLine.from - diff,
drawLine.to + diff,
drawLine.to - diff,
};
var minX = offsets[0].dx;
var maxX = offsets[0].dx;
var minY = offsets[0].dy;
var maxY = offsets[0].dy;
for (int i = 1; i < offsets.Length; i++)
{
minX = Math.Min(minX, offsets[i].dx);
maxX = Math.Max(maxX, offsets[i].dx);
minY = Math.Min(minY, offsets[i].dy);
maxY = Math.Min(maxY, offsets[i].dy);
}
this.addPaintBounds(Rect.fromLTRB(minX, minY, maxX, maxY));
}
}
else if (drawCmd is DrawSaveLayer) {
this.stack.Push(new CanvasRec(
this._transform,
this._clipRect,
this._isInLayer,
this._paintBounds
));
var drawSaveLayer = (DrawSaveLayer) drawCmd;
this._transform = Matrix4x4.identity;
this._clipRect = drawSaveLayer.rect;
this._isInLayer = true;
this._paintBounds = null;
} else if (drawCmd is DrawRestore) {
var isLayer = this._isInLayer;
var state = this._stack.Pop();
this._transform = state.transform;
this._clipRect = state.clipRect;
this._isInLayer = state.isInLayer;
if (isLayer) {
var paintBounds = this._paintBounds;
this._paintBounds = state.paintBounds;
this.addPaintBounds(paintBounds);
}
} else if (drawCmd is DrawClipRect) {
var drawClipRect = (DrawClipRect) drawCmd;
this.addClipRect(drawClipRect.rect);
} else if (drawCmd is DrawClipRRect) {
var drawClipRRect = (DrawClipRRect) drawCmd;
this.addClipRect(drawClipRRect.rrect.outerRect);
} else if (drawCmd is DrawTextBlob)
{
var drawTextBlob = (DrawTextBlob) drawCmd;
var bounds = drawTextBlob.textBlob.boundsInText.shift(drawTextBlob.offset);
this.addPaintBounds(bounds);
} else if (drawCmd is DrawImageRect) {
var drawImageRect = (DrawImageRect) drawCmd;
this.addPaintBounds(drawImageRect.dest);
} else {
throw new Exception("unknown drawCmd: " + drawCmd);
}
}
private void addClipRect(Rect rect) {
if (rect.isInfinite) {
return;
}
if (this._clipRect != null) {
throw new Exception("already a clipRec, considering using saveLayer.");
}
this._clipRect = this._transform.transformRect(rect);
}
private void addPaintBounds(Rect paintBounds) {
if (paintBounds == null) {
return;
}
paintBounds = this._transform.transformRect(paintBounds);
if (this._clipRect != null) {
paintBounds = paintBounds.intersect(this._clipRect);
}
this._paintBounds = this._paintBounds == null
? paintBounds
: this._paintBounds.expandToInclude(paintBounds);
}
private void addPaintBounds(Offset[] points) {
var paintBounds = this._transform.transformRect(points);
if (this._clipRect != null) {
paintBounds = paintBounds.intersect(this._clipRect);
}
this._paintBounds = this._paintBounds == null
? paintBounds
: this._paintBounds.expandToInclude(paintBounds);
}
private class CanvasRec {
public CanvasRec(Matrix4x4 transform, Rect clipRect, bool isInLayer, Rect paintBounds) {
this.transform = transform;
this.clipRect = clipRect;
this.isInLayer = isInLayer;
this.paintBounds = paintBounds;
}
public readonly Matrix4x4 transform;
public readonly Rect clipRect;
public readonly bool isInLayer;
public readonly Rect paintBounds;
}
}
}