namespace XFESystem.Branding;
/// <summary>Allocation-free, integer-only boot artwork. No fonts, text, OS or runtime APIs.</summary>
public static unsafe class BootVisual
{
public const int IntroMilliseconds = 2400;
public const uint Cyan = 0x20C9FF;
public static bool ShouldRelease(ulong elapsedMilliseconds, bool applicationReady) =>
applicationReady && elapsedMilliseconds >= IntroMilliseconds;
public static bool IsWaiting(ulong elapsedMilliseconds, bool applicationReady) =>
!applicationReady && elapsedMilliseconds >= IntroMilliseconds;
public static int LogoSize(int width, int height)
{ int value = (width < height ? width : height) / 5; return value < 80 ? 80 : value > 288 ? 288 : value; }
public static int CenterY(int height) => height * 42 / 100;
public static int LoaderY(int width, int height) => CenterY(height) + LogoSize(width, height) / 2 + LogoSize(width, height) / 12 * 20 / 12 + 62;
/// <summary>Caller owns the mapped extent; only the central animation region is updated.</summary>
public static void Draw(uint* pixels, int width, int height, int stride, ulong milliseconds,
bool waiting, int redShift = 16, int greenShift = 8, int blueShift = 0)
{
if (pixels == null || width < 320 || height < 240 || width > 16384 || height > 16384 || stride < width) return;
int size = LogoSize(width, height), cx = width / 2, cy = CenterY(height);
int top = cy - size - 12, bottom = LoaderY(width, height) + 32;
for (int y = top < 0 ? 0 : top; y < bottom && y < height; y++)
for (int x = cx - size - 12; x <= cx + size + 12; x++)
if (x >= 0 && x < width) pixels[y * stride + x] = 0;
int age = milliseconds > IntroMilliseconds ? IntroMilliseconds : (int)milliseconds;
if (age < 160) return;
int opacity = Ease((age - 160) * 255 / 950);
int reveal = (age - 160) * 55 / 850;
int drawnSize = size * (920 + 80 * opacity / 255) / 1000;
int left = cx - drawnSize / 2, logoTop = cy - drawnSize / 2;
fixed (char* data = BootLogoData.Pixels)
{
for (int y = 0; y < drawnSize; y++)
for (int x = 0; x < drawnSize; x++)
{
int sx = x * 64 / drawnSize, sy = y * 64 / drawnSize;
int dx = sx - 32, dy = sy - 32;
if (reveal < 48 && dx * dx + dy * dy > reveal * reveal) continue;
int at = (sy * 64 + sx) * 2;
uint rgb565 = data[at]; int alpha = (data[at + 1] - 32) * opacity / 255;
if (alpha <= 0) continue;
uint rgb = ((rgb565 >> 11) * 255 / 31 << 16) |
(((rgb565 >> 5) & 63) * 255 / 63 << 8) | ((rgb565 & 31) * 255 / 31);
int scan = (age - 950) * 140 / 850 - 50;
int band = sx + sy - scan;
if (age > 950 && age < 1850 && band > -5 && band < 5)
rgb = Blend(rgb, 0xD7F8FF, (uint)((5 - (band < 0 ? -band : band)) * 24));
Put(pixels, width, height, stride, left + x, logoTop + y, Dim(rgb, alpha), redShift, greenShift, blueShift);
}
}
// The only typography during loading is the product's requested wordmark.
int cell = size / 12, markHeight = cell * 20 / 12, gap = size / 70;
if (gap < 1) gap = 1;
int markWidth = 9 * cell + 8 * gap, markLeft = cx - markWidth / 2, markTop = cy + size / 2 + 20;
int markOpacity = Ease((age - 700) * 255 / 900);
fixed (char* mark = BootLogoData.Wordmark)
for (int glyph = 0; glyph < 9; glyph++)
for (int y = 0; y < markHeight; y++)
for (int x = 0; x < cell; x++)
{
int alpha = (mark[glyph * 240 + y * 20 / markHeight * 12 + x * 12 / cell] - 32) * markOpacity / 255;
if (alpha != 0) Put(pixels, width, height, stride, markLeft + glyph * (cell + gap) + x, markTop + y,
Dim(0xDBF2FF, alpha), redShift, greenShift, blueShift);
}
if (age < 2000)
{
int fade = age < 600 ? (age - 160) * 180 / 440 : (2000 - age) * 180 / 1400;
if (fade > 180) fade = 180;
int phase = (int)(milliseconds % 1400) * 256 / 1400;
Arc(pixels, width, height, stride, cx, cy, size * 3 / 4, phase, 120, Dim(Cyan, fade), redShift, greenShift, blueShift);
Arc(pixels, width, height, stride, cx, cy, size * 3 / 4 + 5, phase + 138, 20, Dim(Cyan, fade / 3), redShift, greenShift, blueShift);
}
if (!waiting) return;
int ly = LoaderY(width, height), radius = size / 10;
if (radius < 12) radius = 12;
int turn = (int)(milliseconds % 1200) * 256 / 1200;
for (int tick = 0; tick < 12; tick++)
{
int phase = tick * 256 / 12;
int distance = ((int)(milliseconds / 75) - tick + 12000) % 12;
int light = distance < 5 ? 255 - distance * 43 : 25;
int x1 = cx + Cos(phase) * (radius - 3) / 1024, y1 = ly + Sin(phase) * (radius - 3) / 1024;
int x2 = cx + Cos(phase) * radius / 1024, y2 = ly + Sin(phase) * radius / 1024;
Line(pixels, width, height, stride, x1, y1, x2, y2, Dim(distance == 0 ? 0xC4F4FF : Cyan, light), redShift, greenShift, blueShift);
}
Arc(pixels, width, height, stride, cx, ly, radius + 6, -turn, 42, Dim(Cyan, 130), redShift, greenShift, blueShift);
Arc(pixels, width, height, stride, cx, ly, radius + 6, -turn + 128, 12, Dim(Cyan, 55), redShift, greenShift, blueShift);
Put(pixels, width, height, stride, cx, ly, Dim(Cyan, 120 + Sin(turn) * 50 / 1024), redShift, greenShift, blueShift);
}
private static int Ease(int value)
{ if (value < 0) return 0; if (value > 255) return 255; return value * value * (765 - 2 * value) / 65025; }
private static uint Dim(uint rgb, int light)
{ if (light < 0) light = 0; if (light > 255) light = 255; return ((rgb >> 16) * (uint)light / 255 << 16) | (((rgb >> 8) & 255) * (uint)light / 255 << 8) | ((rgb & 255) * (uint)light / 255); }
private static uint Blend(uint a, uint b, uint amount) =>
(((a >> 16) * (255 - amount) + (b >> 16) * amount) / 255 << 16) |
((((a >> 8) & 255) * (255 - amount) + ((b >> 8) & 255) * amount) / 255 << 8) |
(((a & 255) * (255 - amount) + (b & 255) * amount) / 255);
private static int Sin(int phase)
{
phase &= 255;
int index = phase & 63;
int value = BootLogoData.QuarterSine[(phase & 64) == 0 ? index : 64 - index];
return (phase & 128) == 0 ? value : -value;
}
private static int Cos(int phase) => Sin(phase + 64);
private static void Put(uint* pixels, int width, int height, int stride, int x, int y, uint rgb, int r, int g, int b)
{ if (x >= 0 && y >= 0 && x < width && y < height) pixels[y * stride + x] = ((rgb >> 16) << r) | (((rgb >> 8) & 255) << g) | ((rgb & 255) << b); }
private static void Arc(uint* pixels, int width, int height, int stride, int cx, int cy, int radius, int start, int length, uint rgb, int r, int g, int b)
{
for (int phase = start; phase < start + length; phase++)
Line(pixels, width, height, stride, cx + Cos(phase) * radius / 1024, cy + Sin(phase) * radius / 1024,
cx + Cos(phase + 1) * radius / 1024, cy + Sin(phase + 1) * radius / 1024, rgb, r, g, b);
}
private static void Line(uint* pixels, int width, int height, int stride, int x, int y, int endX, int endY, uint rgb, int r, int g, int b)
{
int dx = endX - x; if (dx < 0) dx = -dx;
int dy = endY - y; if (dy > 0) dy = -dy;
int sx = x < endX ? 1 : -1, sy = y < endY ? 1 : -1, error = dx + dy;
for (;;)
{
Put(pixels, width, height, stride, x, y, rgb, r, g, b);
if (x == endX && y == endY) return;
int twice = 2 * error;
if (twice >= dy) { error += dy; x += sx; }
if (twice <= dx) { error += dx; y += sy; }
}
}
}
namespace XFESystem.Branding;
/// <summary>Allocation-free, integer-only boot artwork. No fonts, text, OS or runtime APIs.</summary>
public static unsafe class BootVisual
{
public const int IntroMilliseconds = 2400;
public const uint Cyan = 0x20C9FF;
public static bool ShouldRelease(ulong elapsedMilliseconds, bool applicationReady) =>
applicationReady && elapsedMilliseconds >= IntroMilliseconds;
public static bool IsWaiting(ulong elapsedMilliseconds, bool applicationReady) =>
!applicationReady && elapsedMilliseconds >= IntroMilliseconds;
public static int LogoSize(int width, int height)
{ int value = (width < height ? width : height) / 5; return value < 80 ? 80 : value > 288 ? 288 : value; }
public static int CenterY(int height) => height * 42 / 100;
public static int LoaderY(int width, int height) => CenterY(height) + LogoSize(width, height) / 2 + LogoSize(width, height) / 12 * 20 / 12 + 62;
/// <summary>Caller owns the mapped extent; only the central animation region is updated.</summary>
public static void Draw(uint* pixels, int width, int height, int stride, ulong milliseconds,
bool waiting, int redShift = 16, int greenShift = 8, int blueShift = 0)
{
if (pixels == null || width < 320 || height < 240 || width > 16384 || height > 16384 || stride < width) return;
int size = LogoSize(width, height), cx = width / 2, cy = CenterY(height);
int top = cy - size - 12, bottom = LoaderY(width, height) + 32;
for (int y = top < 0 ? 0 : top; y < bottom && y < height; y++)
for (int x = cx - size - 12; x <= cx + size + 12; x++)
if (x >= 0 && x < width) pixels[y * stride + x] = 0;
int age = milliseconds > IntroMilliseconds ? IntroMilliseconds : (int)milliseconds;
if (age < 160) return;
int opacity = Ease((age - 160) * 255 / 950);
int reveal = (age - 160) * 55 / 850;
int drawnSize = size * (920 + 80 * opacity / 255) / 1000;
int left = cx - drawnSize / 2, logoTop = cy - drawnSize / 2;
fixed (char* data = BootLogoData.Pixels)
{
for (int y = 0; y < drawnSize; y++)
for (int x = 0; x < drawnSize; x++)
{
int sx = x * 64 / drawnSize, sy = y * 64 / drawnSize;
int dx = sx - 32, dy = sy - 32;
if (reveal < 48 && dx * dx + dy * dy > reveal * reveal) continue;
int at = (sy * 64 + sx) * 2;
uint rgb565 = data[at]; int alpha = (data[at + 1] - 32) * opacity / 255;
if (alpha <= 0) continue;
uint rgb = ((rgb565 >> 11) * 255 / 31 << 16) |
(((rgb565 >> 5) & 63) * 255 / 63 << 8) | ((rgb565 & 31) * 255 / 31);
int scan = (age - 950) * 140 / 850 - 50;
int band = sx + sy - scan;
if (age > 950 && age < 1850 && band > -5 && band < 5)
rgb = Blend(rgb, 0xD7F8FF, (uint)((5 - (band < 0 ? -band : band)) * 24));
Put(pixels, width, height, stride, left + x, logoTop + y, Dim(rgb, alpha), redShift, greenShift, blueShift);
}
}
// The only typography during loading is the product's requested wordmark.
int cell = size / 12, markHeight = cell * 20 / 12, gap = size / 70;
if (gap < 1) gap = 1;
int markWidth = 9 * cell + 8 * gap, markLeft = cx - markWidth / 2, markTop = cy + size / 2 + 20;
int markOpacity = Ease((age - 700) * 255 / 900);
fixed (char* mark = BootLogoData.Wordmark)
for (int glyph = 0; glyph < 9; glyph++)
for (int y = 0; y < markHeight; y++)
for (int x = 0; x < cell; x++)
{
int alpha = (mark[glyph * 240 + y * 20 / markHeight * 12 + x * 12 / cell] - 32) * markOpacity / 255;
if (alpha != 0) Put(pixels, width, height, stride, markLeft + glyph * (cell + gap) + x, markTop + y,
Dim(0xDBF2FF, alpha), redShift, greenShift, blueShift);
}
if (age < 2000)
{
int fade = age < 600 ? (age - 160) * 180 / 440 : (2000 - age) * 180 / 1400;
if (fade > 180) fade = 180;
int phase = (int)(milliseconds % 1400) * 256 / 1400;
Arc(pixels, width, height, stride, cx, cy, size * 3 / 4, phase, 120, Dim(Cyan, fade), redShift, greenShift, blueShift);
Arc(pixels, width, height, stride, cx, cy, size * 3 / 4 + 5, phase + 138, 20, Dim(Cyan, fade / 3), redShift, greenShift, blueShift);
}
if (!waiting) return;
int ly = LoaderY(width, height), radius = size / 10;
if (radius < 12) radius = 12;
int turn = (int)(milliseconds % 1200) * 256 / 1200;
for (int tick = 0; tick < 12; tick++)
{
int phase = tick * 256 / 12;
int distance = ((int)(milliseconds / 75) - tick + 12000) % 12;
int light = distance < 5 ? 255 - distance * 43 : 25;
int x1 = cx + Cos(phase) * (radius - 3) / 1024, y1 = ly + Sin(phase) * (radius - 3) / 1024;
int x2 = cx + Cos(phase) * radius / 1024, y2 = ly + Sin(phase) * radius / 1024;
Line(pixels, width, height, stride, x1, y1, x2, y2, Dim(distance == 0 ? 0xC4F4FF : Cyan, light), redShift, greenShift, blueShift);
}
Arc(pixels, width, height, stride, cx, ly, radius + 6, -turn, 42, Dim(Cyan, 130), redShift, greenShift, blueShift);
Arc(pixels, width, height, stride, cx, ly, radius + 6, -turn + 128, 12, Dim(Cyan, 55), redShift, greenShift, blueShift);
Put(pixels, width, height, stride, cx, ly, Dim(Cyan, 120 + Sin(turn) * 50 / 1024), redShift, greenShift, blueShift);
}
private static int Ease(int value)
{ if (value < 0) return 0; if (value > 255) return 255; return value * value * (765 - 2 * value) / 65025; }
private static uint Dim(uint rgb, int light)
{ if (light < 0) light = 0; if (light > 255) light = 255; return ((rgb >> 16) * (uint)light / 255 << 16) | (((rgb >> 8) & 255) * (uint)light / 255 << 8) | ((rgb & 255) * (uint)light / 255); }
private static uint Blend(uint a, uint b, uint amount) =>
(((a >> 16) * (255 - amount) + (b >> 16) * amount) / 255 << 16) |
((((a >> 8) & 255) * (255 - amount) + ((b >> 8) & 255) * amount) / 255 << 8) |
(((a & 255) * (255 - amount) + (b & 255) * amount) / 255);
private static int Sin(int phase)
{
phase &= 255;
int index = phase & 63;
int value = BootLogoData.QuarterSine[(phase & 64) == 0 ? index : 64 - index];
return (phase & 128) == 0 ? value : -value;
}
private static int Cos(int phase) => Sin(phase + 64);
private static void Put(uint* pixels, int width, int height, int stride, int x, int y, uint rgb, int r, int g, int b)
{ if (x >= 0 && y >= 0 && x < width && y < height) pixels[y * stride + x] = ((rgb >> 16) << r) | (((rgb >> 8) & 255) << g) | ((rgb & 255) << b); }
private static void Arc(uint* pixels, int width, int height, int stride, int cx, int cy, int radius, int start, int length, uint rgb, int r, int g, int b)
{
for (int phase = start; phase < start + length; phase++)
Line(pixels, width, height, stride, cx + Cos(phase) * radius / 1024, cy + Sin(phase) * radius / 1024,
cx + Cos(phase + 1) * radius / 1024, cy + Sin(phase + 1) * radius / 1024, rgb, r, g, b);
}
private static void Line(uint* pixels, int width, int height, int stride, int x, int y, int endX, int endY, uint rgb, int r, int g, int b)
{
int dx = endX - x; if (dx < 0) dx = -dx;
int dy = endY - y; if (dy > 0) dy = -dy;
int sx = x < endX ? 1 : -1, sy = y < endY ? 1 : -1, error = dx + dy;
for (;;)
{
Put(pixels, width, height, stride, x, y, rgb, r, g, b);
if (x == endX && y == endY) return;
int twice = 2 * error;
if (twice >= dy) { error += dy; x += sx; }
if (twice <= dx) { error += dx; y += sy; }
}
}
}