Files
s&box team 71f266059a Open source release
This commit imports the C# engine code and game files, excluding C++ source code.

[Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
2025-11-24 09:05:18 +00:00

144 lines
3.8 KiB
C#

using SkiaSharp;
using System;
using System.Linq;
namespace Topten.RichTextKit
{
/// <summary>
/// Desribes a gradient to apply to the text
/// </summary>
public class TextGradient
{
public SKPoint Center { get; set; }
public RadialSizeMode SizeMode { get; set; }
public GradientType GradientType { get; set; }
public SKColor[] Colors { get; set; }
public float[] Positions { get; set; }
public float Angle { get; set; }
public static TextGradient Linear( SKColor[] colors, float[] positions, float angle )
{
return new TextGradient()
{
GradientType = GradientType.Linear,
Colors = colors,
Positions = positions,
Angle = angle
};
}
public static TextGradient Radial( SKColor[] colors, float[] positions, float angle, SKPoint center, RadialSizeMode sizeMode )
{
return new TextGradient()
{
GradientType = GradientType.Radial,
Colors = colors,
Positions = positions,
Angle = angle,
Center = center,
SizeMode = sizeMode
};
}
internal SKShader CreateShader( float width, float height, float offsetx = 0 )
{
var rotation = SKMatrix.CreateRotationDegrees( 180 + Angle, width * .5f, height * .5f );
var startPoint = new SKPoint( width * .5f, 0 );
var endPoint = new SKPoint( width * .5f, height );
startPoint = rotation.MapPoint( startPoint );
endPoint = rotation.MapPoint( endPoint );
var localMatrix = SKMatrix.CreateTranslation( offsetx, 0 );
if ( GradientType == GradientType.Linear )
{
var sx = Math.Abs( endPoint.X - startPoint.X );
var sy = Math.Abs( endPoint.Y - startPoint.Y );
if ( sx == 0 ) sx = 1;
if ( sy == 0 ) sy = 1;
sx = width / sx;
sy = height / sy;
var localScale = SKMatrix.CreateScale( sx, sy, width * .5f, height * .5f );
localMatrix = SKMatrix.Concat( localMatrix, localScale );
return SKShader.CreateLinearGradient( startPoint, endPoint, Colors, Positions, SKShaderTileMode.Clamp, localMatrix );
}
if ( GradientType == GradientType.Radial )
{
var center = new SKPoint( width * Center.X, height * Center.Y );
var radius = Math.Max( width, height );
var scaleY = 1.0f;
var scaleX = 1.0f;
var top = center.Y;
var bottom = height - center.Y;
var left = center.X;
var right = width - center.X;
var tl = center;
var tr = new SKPoint( width, 0 ) - center;
var br = new SKPoint( width, height ) - center;
var bl = new SKPoint( 0, height ) - center;
switch ( SizeMode )
{
case RadialSizeMode.Circle:
case RadialSizeMode.FarthestSide:
scaleX = Math.Max( left, right ) / width;
scaleY = Math.Max( top, bottom ) / height;
break;
case RadialSizeMode.FarthestCorner:
var furthestCorner = new SKPoint[] { tl, tr, br, bl }.OrderByDescending( x => x.Length ).First();
scaleX = furthestCorner.X / (width * .71f);
scaleY = furthestCorner.Y / (height * .71f);
break;
case RadialSizeMode.ClosestSide:
scaleX = Math.Min( left, right ) / width;
scaleY = Math.Min( top, bottom ) / height;
break;
case RadialSizeMode.ClosestCorner:
var closestCorner = new SKPoint[] { tl, tr, br, bl }.OrderBy( x => x.Length ).First();
scaleX = closestCorner.X / (width * .71f);
scaleY = closestCorner.Y / (height * .71f);
break;
}
if ( SizeMode != RadialSizeMode.Circle )
{
scaleX *= width / radius;
scaleY *= height / radius;
}
localMatrix = SKMatrix.Concat( localMatrix, SKMatrix.CreateScale( scaleX, scaleY, center.X, center.Y ) );
return SKShader.CreateRadialGradient( center, radius, Colors, Positions, SKShaderTileMode.Clamp, localMatrix );
}
return null;
}
}
public enum GradientType
{
Linear = 0,
Radial = 1
}
public enum RadialSizeMode
{
FarthestSide = 0,
FarthestCorner = 1,
ClosestSide = 2,
ClosestCorner = 3,
Circle = 4
}
}