csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
6.8 KiB
164 lines
6.8 KiB
using System.Diagnostics;
|
|
using Avalonia.Media;
|
|
using Avalonia.Platform;
|
|
|
|
namespace Avalonia.Rendering.Composition.Server;
|
|
|
|
partial class ServerCompositionVisual
|
|
{
|
|
// Dirty flags, handled by RecomputeOwnProperties
|
|
private bool _combinedTransformDirty;
|
|
private bool _clipSizeDirty;
|
|
private bool _ownBoundsDirty;
|
|
private bool _compositionFieldsDirty;
|
|
private bool _contentChanged;
|
|
|
|
private bool _delayPropagateNeedsBoundsUpdate;
|
|
private bool _delayPropagateIsDirtyForRender;
|
|
private bool _delayPropagateHasExtraDirtyRects;
|
|
|
|
// Dirty rect, re-render flags, set by PropagateFlags
|
|
private bool _needsBoundingBoxUpdate;
|
|
private bool _isDirtyForRender;
|
|
private bool _isDirtyForRenderInSubgraph;
|
|
|
|
// Transform that accounts for offset, RenderTransform and other properties of _this_ visual that is
|
|
// used to transform to parent's coordinate space
|
|
// Updated by RecomputeOwnProperties pass
|
|
private Matrix? _ownTransform;
|
|
public Matrix? OwnTransform => _ownTransform;
|
|
|
|
// The bounds of this visual's own content, excluding children
|
|
// Coordinate space: local
|
|
// Updated by RecomputeOwnProperties pass
|
|
private LtrbRect? _ownContentBounds;
|
|
|
|
// The bounds of this visual and its subtree
|
|
// Coordinate space: local
|
|
// Updated by: PreSubgraph, PostSubraph (recursive)
|
|
private LtrbRect? _subTreeBounds;
|
|
|
|
public LtrbRect? SubTreeBounds => _subTreeBounds;
|
|
|
|
// The bounds of this visual and its subtree
|
|
// Coordinate space: parent
|
|
// Updated by: PostSubgraph
|
|
private LtrbRect? _transformedSubTreeBounds;
|
|
|
|
// Visual's own clip area
|
|
// Coordinate space: local
|
|
private LtrbRect? _ownClipRect;
|
|
|
|
|
|
private bool _needsToAddExtraDirtyRectToDirtyRegion;
|
|
private LtrbRect _extraDirtyRect;
|
|
|
|
public virtual LtrbRect? ComputeOwnContentBounds() => null;
|
|
|
|
public Matrix CombinedTransformMatrix { get; private set; } = Matrix.Identity;
|
|
|
|
|
|
// WPF's cheatsheet
|
|
//-----------------------------------------------------------------------------
|
|
// Node Operation | NeedsToBe | NeedsBBoxUpdate | HasNodeThat | Visit
|
|
// | AddedToDirty | (parent chain) | NeedsToBeAdded | child
|
|
// | Region | | ToDirtyRegion |
|
|
// | | | (parent chain) |
|
|
//=============================================================================
|
|
// Set transform | Y | Y | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// Set opacity | Y | N | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// Set clip | Y | Y | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// AttachRenderData | Y | Y | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// FreeRenderData | Y | Y | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// InsertChild | N | Y | Y
|
|
// | Y(child) | N | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// InsertChildAt | N | Y | Y
|
|
// | Y(child) | N | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// ZOrderChild | N | N | Y
|
|
// | Y(child) | N | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// ReplaceChild | Y | Y | Y(N)
|
|
// -----------------+---------------+-----------------+-----------------------
|
|
// RemoveChild | Y | Y | Y(N)
|
|
private void PropagateFlags(bool fNeedsBoundingBoxUpdate, bool fDirtyForRender, bool fAdditionalDirtyRegion = false)
|
|
{
|
|
Root?.RequestUpdate();
|
|
|
|
var parent = Parent;
|
|
var setIsDirtyForRenderInSubgraph = fAdditionalDirtyRegion || fDirtyForRender;
|
|
while (parent != null &&
|
|
((fNeedsBoundingBoxUpdate && !parent._needsBoundingBoxUpdate) ||
|
|
(setIsDirtyForRenderInSubgraph && !parent._isDirtyForRenderInSubgraph)))
|
|
{
|
|
parent._needsBoundingBoxUpdate |= fNeedsBoundingBoxUpdate;
|
|
parent._isDirtyForRenderInSubgraph |= setIsDirtyForRenderInSubgraph;
|
|
|
|
parent = parent.Parent;
|
|
}
|
|
|
|
_needsBoundingBoxUpdate |= fNeedsBoundingBoxUpdate;
|
|
_isDirtyForRender |= fDirtyForRender;
|
|
|
|
// If node itself is dirty for render, we don't need to keep track of extra dirty rects
|
|
_needsToAddExtraDirtyRectToDirtyRegion = !fDirtyForRender && (_needsToAddExtraDirtyRectToDirtyRegion || fAdditionalDirtyRegion);
|
|
}
|
|
|
|
public void RecomputeOwnProperties()
|
|
{
|
|
var setDirtyBounds = _contentChanged || _delayPropagateNeedsBoundsUpdate;
|
|
var setDirtyForRender = _contentChanged || _delayPropagateIsDirtyForRender;
|
|
var setHasExtraDirtyRect = _delayPropagateHasExtraDirtyRects;
|
|
|
|
_delayPropagateIsDirtyForRender =
|
|
_delayPropagateHasExtraDirtyRects =
|
|
_delayPropagateIsDirtyForRender = false;
|
|
|
|
_enqueuedForOwnPropertiesRecompute = false;
|
|
if (_ownBoundsDirty)
|
|
{
|
|
_ownContentBounds = ComputeOwnContentBounds()?.NullIfZeroSize();
|
|
setDirtyForRender = setDirtyBounds = true;
|
|
}
|
|
|
|
if (_clipSizeDirty)
|
|
{
|
|
LtrbRect? clip = null;
|
|
if (Clip != null)
|
|
clip = new(Clip.Bounds);
|
|
if (ClipToBounds)
|
|
{
|
|
var bounds = new LtrbRect(0, 0, Size.X, Size.Y);
|
|
clip = clip?.IntersectOrEmpty(bounds) ?? bounds;
|
|
}
|
|
|
|
if (_ownClipRect != clip)
|
|
{
|
|
_ownClipRect = clip;
|
|
setDirtyForRender = setDirtyBounds = true;
|
|
}
|
|
}
|
|
|
|
if (_combinedTransformDirty)
|
|
{
|
|
_ownTransform = MatrixUtils.ComputeTransform(Size, AnchorPoint, CenterPoint, TransformMatrix, Scale,
|
|
RotationAngle, Orientation, Offset);
|
|
|
|
setDirtyForRender = setDirtyBounds = true;
|
|
|
|
ActHelper_CombinedTransformChanged();
|
|
}
|
|
|
|
|
|
setDirtyForRender |= _compositionFieldsDirty;
|
|
|
|
_ownBoundsDirty = _clipSizeDirty = _combinedTransformDirty = _compositionFieldsDirty = false;
|
|
PropagateFlags(setDirtyBounds, setDirtyForRender, setHasExtraDirtyRect);
|
|
}
|
|
}
|
|
|