Этап 8
This commit is contained in:
@@ -1,19 +1,39 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Minint.Core.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A single raster layer. Pixels are indices into the parent document's palette.
|
||||
/// Array layout is row-major: Pixels[y * width + x].
|
||||
/// </summary>
|
||||
public sealed class MinintLayer
|
||||
public sealed class MinintLayer : INotifyPropertyChanged
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool IsVisible { get; set; }
|
||||
private string _name;
|
||||
private bool _isVisible;
|
||||
private byte _opacity;
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set { if (_name != value) { _name = value; Notify(); } }
|
||||
}
|
||||
|
||||
public bool IsVisible
|
||||
{
|
||||
get => _isVisible;
|
||||
set { if (_isVisible != value) { _isVisible = value; Notify(); } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Per-layer opacity (0 = fully transparent, 255 = fully opaque).
|
||||
/// Used during compositing: effective alpha = paletteColor.A * Opacity / 255.
|
||||
/// </summary>
|
||||
public byte Opacity { get; set; }
|
||||
public byte Opacity
|
||||
{
|
||||
get => _opacity;
|
||||
set { if (_opacity != value) { _opacity = value; Notify(); } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Palette indices, length must equal container Width * Height.
|
||||
@@ -23,9 +43,9 @@ public sealed class MinintLayer
|
||||
|
||||
public MinintLayer(string name, int pixelCount)
|
||||
{
|
||||
Name = name;
|
||||
IsVisible = true;
|
||||
Opacity = 255;
|
||||
_name = name;
|
||||
_isVisible = true;
|
||||
_opacity = 255;
|
||||
Pixels = new int[pixelCount];
|
||||
}
|
||||
|
||||
@@ -34,9 +54,13 @@ public sealed class MinintLayer
|
||||
/// </summary>
|
||||
public MinintLayer(string name, bool isVisible, byte opacity, int[] pixels)
|
||||
{
|
||||
Name = name;
|
||||
IsVisible = isVisible;
|
||||
Opacity = opacity;
|
||||
_name = name;
|
||||
_isVisible = isVisible;
|
||||
_opacity = opacity;
|
||||
Pixels = pixels;
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
private void Notify([CallerMemberName] string? prop = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
|
||||
}
|
||||
|
||||
49
Minint.Core/Services/Impl/FragmentService.cs
Normal file
49
Minint.Core/Services/Impl/FragmentService.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using Minint.Core.Models;
|
||||
|
||||
namespace Minint.Core.Services.Impl;
|
||||
|
||||
public sealed class FragmentService : IFragmentService
|
||||
{
|
||||
public void CopyFragment(
|
||||
MinintDocument srcDoc, int srcLayerIndex,
|
||||
int srcX, int srcY, int regionWidth, int regionHeight,
|
||||
MinintDocument dstDoc, int dstLayerIndex,
|
||||
int dstX, int dstY,
|
||||
int containerWidth, int containerHeight)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(srcLayerIndex);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(dstLayerIndex);
|
||||
if (srcLayerIndex >= srcDoc.Layers.Count)
|
||||
throw new ArgumentOutOfRangeException(nameof(srcLayerIndex));
|
||||
if (dstLayerIndex >= dstDoc.Layers.Count)
|
||||
throw new ArgumentOutOfRangeException(nameof(dstLayerIndex));
|
||||
|
||||
var srcLayer = srcDoc.Layers[srcLayerIndex];
|
||||
var dstLayer = dstDoc.Layers[dstLayerIndex];
|
||||
|
||||
int clippedSrcX = Math.Max(srcX, 0);
|
||||
int clippedSrcY = Math.Max(srcY, 0);
|
||||
int clippedEndX = Math.Min(srcX + regionWidth, containerWidth);
|
||||
int clippedEndY = Math.Min(srcY + regionHeight, containerHeight);
|
||||
|
||||
for (int sy = clippedSrcY; sy < clippedEndY; sy++)
|
||||
{
|
||||
int dy = dstY + (sy - srcY);
|
||||
if (dy < 0 || dy >= containerHeight) continue;
|
||||
|
||||
for (int sx = clippedSrcX; sx < clippedEndX; sx++)
|
||||
{
|
||||
int dx = dstX + (sx - srcX);
|
||||
if (dx < 0 || dx >= containerWidth) continue;
|
||||
|
||||
int srcIdx = srcLayer.Pixels[sy * containerWidth + sx];
|
||||
if (srcIdx == 0) continue; // skip transparent
|
||||
|
||||
RgbaColor color = srcDoc.Palette[srcIdx];
|
||||
int dstIdx = dstDoc.EnsureColorCached(color);
|
||||
dstLayer.Pixels[dy * containerWidth + dx] = dstIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user