Tidy up logic and move away from raw bytes where possible

This commit is contained in:
Dean Herbert
2018-09-04 13:15:52 +09:00
parent 1603f50809
commit 621b8cab98
16 changed files with 205 additions and 249 deletions

View File

@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Graphics.UserInterface;
using osu.Framework.Testing;
using OpenTK.Graphics;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Tests.Visual
{
@@ -30,33 +31,35 @@ namespace osu.Framework.Tests.Visual
public TestCaseCircularProgress()
{
const int width = 128;
byte[] data = new byte[width * 4];
Rgba32[] data = new Rgba32[width];
gradientTextureHorizontal = new Texture(width, 1, true);
for (int i = 0; i < width; ++i)
{
float brightness = (float)i / (width - 1);
int index = i * 4;
data[index + 0] = (byte)(128 + (1 - brightness) * 127);
data[index + 1] = (byte)(128 + brightness * 127);
data[index + 2] = 128;
data[index + 3] = 255;
data[i] = new Rgba32(
(byte)(128 + (1 - brightness) * 127),
(byte)(128 + brightness * 127),
128,
255);
}
gradientTextureHorizontal.SetData(new TextureUpload(data));
gradientTextureHorizontal.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
gradientTextureVertical = new Texture(1, width, true);
for (int i = 0; i < width; ++i)
{
float brightness = (float)i / (width - 1);
int index = i * 4;
data[index + 0] = (byte)(128 + (1 - brightness) * 127);
data[index + 1] = (byte)(128 + brightness * 127);
data[index + 2] = 128;
data[index + 3] = 255;
data[i] = new Rgba32(
(byte)(128 + (1 - brightness) * 127),
(byte)(128 + brightness * 127),
128,
255);
}
gradientTextureVertical.SetData(new TextureUpload(data));
byte[] data2 = new byte[width * width * 4];
gradientTextureVertical.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
data = new Rgba32[width * width];
gradientTextureBoth = new Texture(width, width, true);
for (int i = 0; i < width; ++i)
{
@@ -64,15 +67,15 @@ namespace osu.Framework.Tests.Visual
{
float brightness = (float)i / (width - 1);
float brightness2 = (float)j / (width - 1);
int index = i * 4 * width + j * 4;
data2[index + 0] = (byte)(128 + (1 + brightness - brightness2) / 2 * 127);
data2[index + 1] = (byte)(128 + (1 + brightness2 - brightness) / 2 * 127);
data2[index + 2] = (byte)(128 + (brightness + brightness2) / 2 * 127);
data2[index + 3] = 255;
data[i * width + j] = new Rgba32(
(byte)(128 + (1 + brightness - brightness2) / 2 * 127),
(byte)(128 + (1 + brightness2 - brightness) / 2 * 127),
(byte)(128 + (brightness + brightness2) / 2 * 127),
255);
}
}
gradientTextureBoth.SetData(new TextureUpload(data2));
gradientTextureBoth.SetData(new TextureUpload(new RawTextureRgba32(width, width, data)));
Children = new Drawable[]
{

View File

@@ -11,6 +11,7 @@ using osu.Framework.Input.States;
using osu.Framework.Testing;
using OpenTK;
using OpenTK.Graphics;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Tests.Visual
{
@@ -20,17 +21,13 @@ namespace osu.Framework.Tests.Visual
{
const int width = 20;
Texture gradientTexture = new Texture(width, 1, true);
byte[] data = new byte[width * 4];
Rgba32[] data = new Rgba32[width];
for (int i = 0; i < width; ++i)
{
float brightness = (float)i / (width - 1);
int index = i * 4;
data[index + 0] = (byte)(brightness * 255);
data[index + 1] = (byte)(brightness * 255);
data[index + 2] = (byte)(brightness * 255);
data[index + 3] = 255;
var brightnessByte = (byte)((float)i / (width - 1) * 255);
data[i] = new Rgba32(brightnessByte, brightnessByte, brightnessByte);
}
gradientTexture.SetData(new TextureUpload(data));
gradientTexture.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
Cell(0).AddRange(new[]
{

View File

@@ -12,6 +12,7 @@ using osu.Framework.Input.States;
using osu.Framework.Testing;
using OpenTK;
using OpenTK.Graphics;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Tests.Visual
{
@@ -22,17 +23,13 @@ namespace osu.Framework.Tests.Visual
{
const int width = 2;
Texture gradientTexture = new Texture(width, 1, true);
byte[] data = new byte[width * 4];
Rgba32[] data = new Rgba32[width];
for (int i = 0; i < width; ++i)
{
float brightness = (float)i / (width - 1);
int index = i * 4;
data[index + 0] = (byte)(brightness * 255);
data[index + 1] = (byte)(brightness * 255);
data[index + 2] = (byte)(brightness * 255);
data[index + 3] = 255;
var brightnessByte = (byte)((float)i / (width - 1) * 255);
data[i] = new Rgba32(brightnessByte, brightnessByte, brightnessByte);
}
gradientTexture.SetData(new TextureUpload(data));
gradientTexture.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
SpriteText[] text = new SpriteText[6];

View File

@@ -49,7 +49,7 @@ namespace osu.Framework.Tests.Visual
var image = t.Result;
var tex = new Texture(image.Width, image.Height);
tex.SetData(new TextureUpload(new RawTexture(image)));
tex.SetData(new TextureUpload(new RawTextureImage(image)));
display.Texture = tex;
}));

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using osu.Framework.Graphics.OpenGL.Textures;
using osu.Framework.Graphics.Textures;
using OpenTK;
using OpenTK.Graphics.ES30;
@@ -60,7 +61,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
if (withTexture)
{
Texture = new TextureGLSingle(1, 1, true, filteringMode);
Texture.SetData(new TextureUpload(Array.Empty<byte>()));
Texture.SetData(new TextureUpload(new RawTextureRgba32(0, 0)));
Texture.Upload();
Bind();
@@ -77,7 +78,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
private Vector2 size = Vector2.One;
/// <summary>
/// Sets the size of the texture of this framebuffer.
/// Sets the size of the texture of this frame buffer.
/// </summary>
public Vector2 Size
{
@@ -90,7 +91,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
Texture.Width = (int)Math.Ceiling(size.X);
Texture.Height = (int)Math.Ceiling(size.Y);
Texture.SetData(new TextureUpload(Array.Empty<byte>()));
Texture.SetData(new TextureUpload(new RawTextureRgba32(0, 0)));
Texture.Upload();
}
}

View File

@@ -12,7 +12,6 @@ using OpenTK.Graphics.ES30;
using osu.Framework.Statistics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.OpenGL.Vertices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.OpenGL.Textures
@@ -325,30 +324,9 @@ namespace osu.Framework.Graphics.OpenGL.Textures
{
while (uploadQueue.TryDequeue(out TextureUpload upload))
{
if (upload.ImageData != null)
{
fixed (Rgba32* ptr = &MemoryMarshal.GetReference(upload.ImageData.GetPixelSpan()))
doUpload(upload, (IntPtr)ptr);
didUpload = true;
}
else
{
IntPtr dataPointer;
if (upload.Data.Length == 0)
{
dataPointer = IntPtr.Zero;
doUpload(upload, dataPointer);
}
else
{
GCHandle h0 = GCHandle.Alloc(upload.Data, GCHandleType.Pinned);
dataPointer = h0.AddrOfPinnedObject();
doUpload(upload, dataPointer);
didUpload = true;
h0.Free();
}
}
fixed (Rgba32* ptr = &MemoryMarshal.GetReference(upload.Data))
doUpload(upload, (IntPtr)ptr);
didUpload = true;
upload.Dispose();
}
}

View File

@@ -5,7 +5,6 @@ using System;
using OpenTK.Graphics.ES30;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Graphics.Textures;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.OpenGL.Textures
@@ -30,27 +29,13 @@ namespace osu.Framework.Graphics.OpenGL.Textures
/// </summary>
public RectangleI Bounds;
/// <summary>
/// The upload data.
/// </summary>
public readonly byte[] Data;
public Image<Rgba32> ImageData;
public ReadOnlySpan<Rgba32> Data => texture.GetImageData();
/// <summary>
/// The backing texture. A handle is kept to avoid early GC.
/// </summary>
private readonly RawTexture texture;
/// <summary>
/// Create an upload with arbitrary raw data.
/// </summary>
/// <param name="data"></param>
public TextureUpload(byte[] data)
{
Data = data;
}
/// <summary>
/// Create an upload from a <see cref="RawTexture"/>. This is the preferred method.
/// </summary>
@@ -58,9 +43,6 @@ namespace osu.Framework.Graphics.OpenGL.Textures
public TextureUpload(RawTexture texture)
{
this.texture = texture;
ImageData = texture.ImageData;
Data = texture.Data;
}
#region IDisposable Support

View File

@@ -20,6 +20,7 @@ using System.Diagnostics;
using System.Linq;
using osu.Framework.Input.EventArgs;
using osu.Framework.Input.States;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.Performance
{
@@ -37,7 +38,7 @@ namespace osu.Framework.Graphics.Performance
private const float alpha_when_active = 0.75f;
private readonly TimeBar[] timeBars;
private readonly BufferStack<byte> textureBufferStack;
private readonly BufferStack<Rgba32> textureBufferStack;
private static readonly Color4[] garbage_collect_colors = { Color4.Green, Color4.Yellow, Color4.Red };
private readonly PerformanceMonitor monitor;
@@ -228,29 +229,29 @@ namespace osu.Framework.Graphics.Performance
}
};
textureBufferStack = new BufferStack<byte>(timeBars.Length * WIDTH);
textureBufferStack = new BufferStack<Rgba32>(timeBars.Length * WIDTH);
}
[BackgroundDependencyLoader]
private void load()
{
//initialise background
byte[] column = new byte[HEIGHT * 4];
byte[] fullBackground = new byte[WIDTH * HEIGHT * 4];
Rgba32[] column = new Rgba32[HEIGHT];
Rgba32[] fullBackground = new Rgba32[WIDTH * HEIGHT];
addArea(null, null, HEIGHT, column, amount_ms_steps);
for (int i = 0; i < HEIGHT; i++)
for (int k = 0; k < WIDTH; k++)
Buffer.BlockCopy(column, i * 4, fullBackground, i * WIDTH * 4 + k * 4, 4);
fullBackground[k] = column[i];
addArea(null, null, HEIGHT, column, amount_count_steps);
counterBarBackground?.Texture.SetData(new TextureUpload(column));
counterBarBackground?.Texture.SetData(new TextureUpload(new RawTextureRgba32(1, HEIGHT, column)));
Schedule(() =>
{
foreach (var t in timeBars)
t.Sprite.Texture.SetData(new TextureUpload(fullBackground));
t.Sprite.Texture.SetData(new TextureUpload(new RawTextureRgba32(WIDTH, HEIGHT, fullBackground)));
});
}
@@ -348,7 +349,8 @@ namespace osu.Framework.Graphics.Performance
private void applyFrameTime(FrameStatistics frame)
{
TimeBar timeBar = timeBars[timeBarIndex];
TextureUpload upload = new TextureUpload(new RawTexture(1, HEIGHT, textureBufferStack))
var raw = new RawTextureBufferStack(1, HEIGHT, textureBufferStack);
TextureUpload upload = new TextureUpload(raw)
{
Bounds = new RectangleI(timeBarX, 0, 1, HEIGHT)
};
@@ -356,8 +358,8 @@ namespace osu.Framework.Graphics.Performance
int currentHeight = HEIGHT;
for (int i = 0; i < FrameStatistics.NUM_PERFORMANCE_COLLECTION_TYPES; i++)
currentHeight = addArea(frame, (PerformanceCollectionType)i, currentHeight, upload.Data, amount_ms_steps);
addArea(frame, null, currentHeight, upload.Data, amount_ms_steps);
currentHeight = addArea(frame, (PerformanceCollectionType)i, currentHeight, raw.Data, amount_ms_steps);
addArea(frame, null, currentHeight, raw.Data, amount_ms_steps);
timeBar.Sprite.Texture.SetData(upload);
@@ -447,9 +449,9 @@ namespace osu.Framework.Graphics.Performance
}
}
private int addArea(FrameStatistics frame, PerformanceCollectionType? frameTimeType, int currentHeight, byte[] textureData, int amountSteps)
private int addArea(FrameStatistics frame, PerformanceCollectionType? frameTimeType, int currentHeight, Rgba32[] textureData, int amountSteps)
{
Trace.Assert(textureData.Length >= HEIGHT * 4, $"textureData is too small ({textureData.Length}) to hold area data.");
Trace.Assert(textureData.Length >= HEIGHT, $"textureData is too small ({textureData.Length}) to hold area data.");
int drawHeight;
@@ -480,11 +482,10 @@ namespace osu.Framework.Graphics.Performance
else if (acceptableRange)
brightnessAdjust *= 0.8f;
int index = i * 4;
textureData[index] = (byte)(255 * col.R * brightnessAdjust);
textureData[index + 1] = (byte)(255 * col.G * brightnessAdjust);
textureData[index + 2] = (byte)(255 * col.B * brightnessAdjust);
textureData[index + 3] = (byte)(255 * col.A);
textureData[i].R= (byte)(255 * col.R * brightnessAdjust);
textureData[i].G= (byte)(255 * col.G * brightnessAdjust);
textureData[i].B= (byte)(255 * col.B * brightnessAdjust);
textureData[i].A= (byte)(255 * col.A);
currentHeight--;
}

View File

@@ -2,18 +2,15 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE
using System;
using System.IO;
using osu.Framework.Allocation;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using PixelFormat = OpenTK.Graphics.ES30.PixelFormat;
namespace osu.Framework.Graphics.Textures
{
/// <summary>
/// Texture data in a raw byte format.
/// Texture data in a raw Rgba32 format.
/// </summary>
public class RawTexture : IDisposable
public abstract class RawTexture : IDisposable
{
/// <summary>
/// The width of the texture data.
@@ -30,85 +27,10 @@ namespace osu.Framework.Graphics.Textures
/// </summary>
public readonly PixelFormat PixelFormat = PixelFormat.Rgba;
/// <summary>
/// The texture data.
/// </summary>
public byte[] Data;
private readonly BufferStack<byte> bufferStack;
/// <summary>
/// Create a raw texture from an arbitrary image stream.
/// </summary>
/// <param name="stream">The image content.</param>
public RawTexture(Stream stream) : this(Image.Load(stream))
{
}
public RawTexture(Image<Rgba32> image)
{
ImageData = image;
Width = ImageData.Width;
Height = ImageData.Height;
}
/// <summary>
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="bufferStack">The buffer stack to retrieve the byte[] from.</param>
public RawTexture(int width, int height, BufferStack<byte> bufferStack = null)
{
int size = width * height * 4;
Width = width;
Height = height;
if (bufferStack != null)
{
this.bufferStack = bufferStack;
Data = this.bufferStack.ReserveBuffer(size);
}
else
{
Data = new byte[size];
}
}
/// <summary>
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The heightof the texture.</param>
/// <param name="data">The raw texture data.</param>
public RawTexture(int width, int height, byte[] data)
{
int size = width * height * 4;
if (size != data.Length)
throw new InvalidOperationException("Provided data does not match dimensions");
Data = data;
Width = width;
Height = height;
}
#region IDisposable Support
private bool disposed;
public Image<Rgba32> ImageData;
protected virtual void Dispose(bool disposing)
{
ImageData?.Dispose();
if (!disposed)
{
disposed = true;
bufferStack?.FreeBuffer(Data);
}
}
~RawTexture()
@@ -123,5 +45,7 @@ namespace osu.Framework.Graphics.Textures
}
#endregion
public abstract ReadOnlySpan<Rgba32> GetImageData();
}
}

View File

@@ -0,0 +1,28 @@
using osu.Framework.Allocation;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.Textures
{
public class RawTextureBufferStack : RawTextureRgba32
{
private readonly BufferStack<Rgba32> bufferStack;
/// <summary>
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="bufferStack">The buffer stack to retrieve the Rgba32[] from.</param>
public RawTextureBufferStack(int width, int height, BufferStack<Rgba32> bufferStack)
: base(width, height, bufferStack.ReserveBuffer(width * height))
{
this.bufferStack = bufferStack;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
bufferStack?.FreeBuffer(Data);
}
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.IO;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.Textures
{
public class RawTextureImage : RawTexture
{
public readonly Image<Rgba32> Data;
/// <summary>
/// Create a raw texture from an arbitrary image stream.
/// </summary>
/// <param name="stream">The image content.</param>
public RawTextureImage(Stream stream)
: this(Image.Load(stream))
{
}
public RawTextureImage(Image<Rgba32> data)
{
Data = data;
Width = Data.Width;
Height = Data.Height;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
Data.Dispose();
}
public override ReadOnlySpan<Rgba32> GetImageData() => Data.GetPixelSpan();
}
}

View File

@@ -26,7 +26,7 @@ namespace osu.Framework.Graphics.Textures
using (var stream = store.GetStream(name))
{
if (stream != null)
return new RawTexture(stream);
return new RawTextureImage(stream);
}
}
catch

View File

@@ -0,0 +1,49 @@
using System;
using System.Runtime.CompilerServices;
using osu.Framework.Allocation;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.Textures
{
public class RawTextureRgba32 : RawTexture
{
/// <summary>
/// The texture data.
/// </summary>
public readonly Rgba32[] Data;
/// <summary>
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="data">The raw texture data.</param>
public RawTextureRgba32(int width, int height, Rgba32[] data = null)
{
if (data == null)
data = new Rgba32[width * height];
if (width * height != data.Length)
throw new InvalidOperationException("Provided data does not match dimensions");
Data = data;
Width = width;
Height = height;
}
/// <summary>
/// Create a raw texture with arbitrary raw data.
/// Note that this method requires a memory copy operation to convert from <see cref="Byte"/> to <see cref="Rgba32"/>.
/// Where possible, use <see cref="RawTextureRgba32"/> instead.
/// </summary>
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="data">The raw texture data.</param>
internal RawTextureRgba32(int width, int height, byte[] data)
: this(width, height, Unsafe.As<Rgba32[]>(data))
{
}
public override ReadOnlySpan<Rgba32> GetImageData() => new Span<Rgba32>(Data);
}
}

View File

@@ -8,6 +8,7 @@ using OpenTK.Graphics.ES30;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Logging;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.Graphics.Textures
{
@@ -69,9 +70,9 @@ namespace osu.Framework.Graphics.Textures
{
// add an empty white rect to use for solid box drawing (shader optimisation).
// see Texture.WhitePixel for usage.
var raw = new RawTexture(whiteTex.Width, whiteTex.Height);
var raw = new RawTextureRgba32(whiteTex.Width, whiteTex.Height);
for (int i = 0; i < raw.Data.Length; i++)
raw.Data[i] = 255;
raw.Data[i] = Rgba32.White;
whiteTex.SetData(new TextureUpload(raw));
}
}

View File

@@ -24,9 +24,9 @@ namespace osu.Framework.Graphics.Textures
try
{
RawTexture data = new RawTexture(stream);
RawTexture data = new RawTextureImage(stream);
Texture tex = atlas == null ? new Texture(data.Width, data.Height) : new Texture(atlas.Add(data.Width, data.Height));
tex.SetData(new TextureUpload(data.Data));
tex.SetData(new TextureUpload(data));
return tex;
}
catch (ArgumentException)
@@ -67,7 +67,7 @@ namespace osu.Framework.Graphics.Textures
Texture tex = atlas == null ? new Texture(width, height) : new Texture(atlas.Add(width, height));
var upload = new TextureUpload(data) { Format = format };
var upload = new TextureUpload(new RawTextureRgba32(width, height, data)) { Format = format };
tex.SetData(upload);
return tex;
}

View File

@@ -9,7 +9,7 @@ using System.IO;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Logging;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
namespace osu.Framework.IO.Stores
{
@@ -25,7 +25,7 @@ namespace osu.Framework.IO.Stores
protected BitmapFont Font => completionSource.Task.Result;
private readonly TimedExpiryCache<int, RawTexture> texturePages = new TimedExpiryCache<int, RawTexture>();
private readonly TimedExpiryCache<int, RawTextureImage> texturePages = new TimedExpiryCache<int, RawTextureImage>();
private readonly TaskCompletionSource<BitmapFont> completionSource = new TaskCompletionSource<BitmapFont>();
@@ -91,82 +91,40 @@ namespace osu.Framework.IO.Stores
private RawTexture loadCharacter(Character c)
{
RawTexture page = getTexturePage(c.TexturePage);
var page = getTexturePage(c.TexturePage);
loadedGlyphCount++;
int width = c.Bounds.Width + c.Offset.X + 1;
int height = c.Bounds.Height + c.Offset.Y + 1;
int length = width * height * 4;
byte[] pixels = new byte[length];
int length = width * height;
var pixels = new Rgba32[length];
var span = page.GetImageData();
if (page.ImageData != null)
for (int y = 0; y < height; y++)
{
var span = page.ImageData.GetPixelSpan();
for (int x = 0; x < width; x++)
{
int dest = y * width + x;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int desti = y * width * 4 + x * 4;
if (x >= c.Offset.X && y >= c.Offset.Y
&& x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
{
int srci = (c.Bounds.Y + y - c.Offset.Y) * page.Width + (c.Bounds.X + x - c.Offset.X);
var col = span[srci];
pixels[desti] = col.R;
pixels[desti + 1] = col.G;
pixels[desti + 2] = col.B;
pixels[desti + 3] = col.A;
}
else
{
pixels[desti] = 255;
pixels[desti + 1] = 255;
pixels[desti + 2] = 255;
pixels[desti + 3] = 0;
}
}
}
}
else
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
int desti = y * width * 4 + x * 4;
if (x >= c.Offset.X && y >= c.Offset.Y
&& x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
{
int srci = (c.Bounds.Y + y - c.Offset.Y) * page.Width * 4
+ (c.Bounds.X + x - c.Offset.X) * 4;
pixels[desti] = page.Data[srci];
pixels[desti + 1] = page.Data[srci + 1];
pixels[desti + 2] = page.Data[srci + 2];
pixels[desti + 3] = page.Data[srci + 3];
}
else
{
pixels[desti] = 255;
pixels[desti + 1] = 255;
pixels[desti + 2] = 255;
pixels[desti + 3] = 0;
}
}
if (x >= c.Offset.X && y >= c.Offset.Y && x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
pixels[dest] = span[(c.Bounds.Y + y - c.Offset.Y) * page.Width + (c.Bounds.X + x - c.Offset.X)];
else
pixels[dest] = new Rgba32(255, 255, 255, 0);
}
}
return new RawTexture(width, height, pixels);
return new RawTextureRgba32(width, height, pixels);
}
private RawTexture getTexturePage(int texturePage)
private RawTextureImage getTexturePage(int texturePage)
{
if (!texturePages.TryGetValue(texturePage, out RawTexture t))
if (!texturePages.TryGetValue(texturePage, out RawTextureImage t))
{
loadedPageCount++;
using (var stream = store.GetStream($@"{assetName}_{texturePage.ToString().PadLeft((Font.Pages.Length - 1).ToString().Length, '0')}.png"))
texturePages.Add(texturePage, t = new RawTexture(stream));
texturePages.Add(texturePage, t = new RawTextureImage(stream));
}
return t;