|
@@ -60,7 +60,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
private bool disposed = false;
|
|
|
private readonly object lockObject = new();
|
|
|
private int commitCounter = 0;
|
|
|
-
|
|
|
+
|
|
|
private RectI cachedPreciseBounds = RectI.Empty;
|
|
|
private int lastBoundsCacheHash = -1;
|
|
|
|
|
@@ -96,7 +96,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
private VectorPath? clippingPath;
|
|
|
private double? horizontalSymmetryAxis = null;
|
|
|
private double? verticalSymmetryAxis = null;
|
|
|
-
|
|
|
+
|
|
|
private int operationCounter = 0;
|
|
|
|
|
|
private readonly Dictionary<ChunkResolution, Dictionary<VecI, Chunk>> committedChunks;
|
|
@@ -202,7 +202,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
RectI scaledCommittedSize = (RectI)(new RectD(VecI.Zero, CommittedSize * multiplier)).RoundOutwards();
|
|
|
|
|
|
RectI? preciseBounds = null;
|
|
|
-
|
|
|
+
|
|
|
foreach (var (chunkPos, fullResChunk) in committedChunks[ChunkResolution.Full])
|
|
|
{
|
|
|
if (committedChunks[suggestedResolution].TryGetValue(chunkPos, out Chunk? requestedResChunk))
|
|
@@ -239,7 +239,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
|
|
|
cachedPreciseBounds = preciseBounds.GetValueOrDefault();
|
|
|
lastBoundsCacheHash = GetCacheHash();
|
|
|
-
|
|
|
+
|
|
|
return preciseBounds;
|
|
|
}
|
|
|
}
|
|
@@ -358,7 +358,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
}
|
|
|
|
|
|
var committedChunk = GetCommittedChunk(chunkPos, resolution);
|
|
|
-
|
|
|
+
|
|
|
// draw committed directly
|
|
|
if (latestChunk.IsT0 || latestChunk.IsT1 && committedChunk is not null && blendMode != BlendMode.Src)
|
|
|
{
|
|
@@ -647,6 +647,51 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Be careful about the copyImage argument. The default is true, and this is a thread safe version without any side effects.
|
|
|
+ /// It will however copy the surface right away which can be slow (in updateable changes especially).
|
|
|
+ /// If copyImage is set to false, the image won't be copied and instead a reference will be stored.
|
|
|
+ /// Texture is NOT THREAD SAFE, so if you pass a Texture here with copyImage == false you must not do anything with that texture anywhere (not even read) until CommitChanges/CancelChanges is called.
|
|
|
+ /// </summary>
|
|
|
+ /// <exception cref="ObjectDisposedException">This image is disposed</exception>
|
|
|
+ public void EnqueueDrawTexture(Matrix3X3 transformMatrix, Texture image, Paint? paint = null, bool copyImage = true)
|
|
|
+ {
|
|
|
+ lock (lockObject)
|
|
|
+ {
|
|
|
+ ThrowIfDisposed();
|
|
|
+ TextureOperation operation = new(transformMatrix, image, paint, copyImage);
|
|
|
+ EnqueueOperation(operation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Be careful about the copyImage argument, see other overload for details
|
|
|
+ /// </summary>
|
|
|
+ /// <exception cref="ObjectDisposedException">This image is disposed</exception>
|
|
|
+ public void EnqueueDrawTexture(ShapeCorners corners, Texture image, Paint? paint = null, bool copyImage = true)
|
|
|
+ {
|
|
|
+ lock (lockObject)
|
|
|
+ {
|
|
|
+ ThrowIfDisposed();
|
|
|
+ TextureOperation operation = new(corners, image, paint, copyImage);
|
|
|
+ EnqueueOperation(operation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Be careful about the copyImage argument, see other overload for details
|
|
|
+ /// </summary>
|
|
|
+ /// <exception cref="ObjectDisposedException">This image is disposed</exception>
|
|
|
+ public void EnqueueDrawTexture(VecI pos, Texture image, Paint? paint = null, bool copyImage = true)
|
|
|
+ {
|
|
|
+ lock (lockObject)
|
|
|
+ {
|
|
|
+ ThrowIfDisposed();
|
|
|
+ TextureOperation operation = new(pos, image, paint, copyImage);
|
|
|
+ EnqueueOperation(operation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
public void EnqueueApplyMask(ChunkyImage mask)
|
|
|
{
|
|
|
lock (lockObject)
|
|
@@ -1435,9 +1480,9 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
|
|
|
public int GetCacheHash()
|
|
|
{
|
|
|
return commitCounter + queuedOperations.Count + operationCounter + activeClips.Count
|
|
|
- + (int)blendMode + (lockTransparency ? 1 : 0)
|
|
|
- + (horizontalSymmetryAxis is not null ? (int)(horizontalSymmetryAxis * 100) : 0)
|
|
|
- + (verticalSymmetryAxis is not null ? (int)(verticalSymmetryAxis * 100) : 0)
|
|
|
- + (clippingPath is not null ? 1 : 0);
|
|
|
+ + (int)blendMode + (lockTransparency ? 1 : 0)
|
|
|
+ + (horizontalSymmetryAxis is not null ? (int)(horizontalSymmetryAxis * 100) : 0)
|
|
|
+ + (verticalSymmetryAxis is not null ? (int)(verticalSymmetryAxis * 100) : 0)
|
|
|
+ + (clippingPath is not null ? 1 : 0);
|
|
|
}
|
|
|
}
|