Пример #1
0
    public override void Render()
    {
        if (Width <= 0 || Height <= 0)
        {
            throw new InvalidOperationException($"{nameof(Render)}: arranger dimensions for '{Arranger.Name}' are too small to render " +
                                                $"({Width}, {Height})");
        }

        if (Width * Height != Image.Length)
        {
            Image = new byte[Width * Height];
        }

        // TODO: Handle undefined elements explicitly and clear image subsections
        Array.Clear(Image, 0, Image.Length);

        var locations = Arranger.EnumerateElementLocationsWithinPixelRange(Left, Top, Width, Height);

        var imageRect = new Rectangle(Left, Top, Width, Height);

        foreach (var location in locations)
        {
            var el = Arranger.GetElement(location.X, location.Y);
            if (el is ArrangerElement element && element.Codec is IIndexedCodec codec)
            {
                var encodedBuffer = codec.ReadElement(element);

                // TODO: Detect reads past end of file more gracefully
                if (encodedBuffer.Length == 0)
                {
                    continue;
                }

                var elementRect = new Rectangle(element.X1, element.Y1, element.Width, element.Height);
                elementRect.Intersect(imageRect);

                if (elementRect.IsEmpty)
                {
                    continue;
                }

                int minX   = Math.Clamp(element.X1, Left, Right - 1);
                int maxX   = Math.Clamp(element.X2, Left, Right - 1);
                int minY   = Math.Clamp(element.Y1, Top, Bottom - 1);
                int maxY   = Math.Clamp(element.Y2, Top, Bottom - 1);
                int deltaX = minX - element.X1;
                int deltaY = minY - element.Y1;

                var decodedImage = codec.DecodeElement(element, encodedBuffer);
                decodedImage.RotateArray2D(element.Rotation);
                decodedImage.MirrorArray2D(element.Mirror);

                for (int y = 0; y <= maxY - minY; y++)
                {
                    int destidx = (element.Y1 + deltaY + y - Top) * Width + (element.X1 + deltaX - Left);
                    for (int x = 0; x <= maxX - minX; x++)
                    {
                        Image[destidx] = decodedImage[y + deltaY, x + deltaX];
                        destidx++;
                    }
                }
            }