/******************************************************************************
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
* CopyRight (C) 2012-2022 ShenYongHua(沈永华).
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
*
* Blog: https://www.cnblogs.com/yhuse
* Gitee: https://gitee.com/yhuse/SunnyUI
* GitHub: https://github.com/yhuse/SunnyUI
*
* SunnyUI.dll can be used for free under the GPL-3.0 license.
* If you use this code, please keep this note.
* 如果您使用此代码,请保留此说明。
******************************************************************************
* 文件名称: UFontImage.cs
* 文件说明: 字体图片帮助类
* 当前版本: V3.1
* 创建日期: 2020-01-01
*
* 2020-01-01: V2.2.0 增加文件说明
* 2020-05-21: V2.2.5 调整从资源文件中加载字体,不用另存为文件。
* 感谢:麦壳饼 https://gitee.com/maikebing
* 2021-06-15: V3.0.4 增加FontAwesomeV5的字体图标,重构代码
******************************************************************************/
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace Sunny.UI
{
///
/// 字体图片帮助类
///
public static class FontImageHelper
{
///
/// AwesomeFont
///
public static readonly FontImages FontAwesomeV4;
///
/// ElegantFont
///
public static readonly FontImages ElegantIcons;
///
/// FontAwesomeV5Brands
///
public static readonly FontImages FontAwesomeV5Brands;
///
/// FontAwesomeV5Regular
///
public static readonly FontImages FontAwesomeV5Regular;
///
/// FontAwesomeV5Solid
///
public static readonly FontImages FontAwesomeV5Solid;
public const int FontAwesomeV4Count = 786;
public const int ElegantIconsCount = 360;
public const int FontAwesomeV5RegularCount = 151;
public const int FontAwesomeV5SolidCount = 1001;
public const int FontAwesomeV5BrandsCount = 457;
///
/// 构造函数
///
static FontImageHelper()
{
FontAwesomeV4 = new FontImages(ReadFontFileFromResource("Sunny.UI.Font.FontAwesome.ttf"));
ElegantIcons = new FontImages(ReadFontFileFromResource("Sunny.UI.Font.ElegantIcons.ttf"));
FontAwesomeV5Brands = new FontImages(ReadFontFileFromResource("Sunny.UI.Font.fa-brands-400.ttf"));
FontAwesomeV5Regular = new FontImages(ReadFontFileFromResource("Sunny.UI.Font.fa-regular-400.ttf"));
FontAwesomeV5Solid = new FontImages(ReadFontFileFromResource("Sunny.UI.Font.fa-solid-900.ttf"));
}
private static byte[] ReadFontFileFromResource(string name)
{
byte[] buffer = null;
Stream fontStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(name);
if (fontStream != null)
{
buffer = new byte[fontStream.Length];
fontStream.Read(buffer, 0, (int)fontStream.Length);
fontStream.Close();
}
return buffer;
}
///
/// 获取字体大小
///
/// GDI绘图
/// 字符
/// 大小
/// 字体大小
public static SizeF GetFontImageSize(this Graphics graphics, int symbol, int symbolSize)
{
Font font = GetFont(symbol, symbolSize);
if (font == null)
{
return new SizeF(0, 0);
}
return graphics.MeasureString(char.ConvertFromUtf32(symbol), font);
}
private static UISymbolType GetSymbolType(int symbol)
{
return (UISymbolType)symbol.Div(100000);
}
private static int GetSymbolValue(int symbol)
{
return symbol.Mod(100000);
}
///
/// 绘制字体图片
///
/// GDI绘图
/// 字符
/// 大小
/// 颜色
/// 区域
/// 左右偏移
/// 上下偏移
public static void DrawFontImage(this Graphics graphics, int symbol, int symbolSize, Color color,
RectangleF rect, int xOffset = 0, int yOffSet = 0)
{
SizeF sf = graphics.GetFontImageSize(symbol, symbolSize);
graphics.DrawFontImage(symbol, symbolSize, color, rect.Left + ((rect.Width - sf.Width) / 2.0f).RoundEx(),
rect.Top + ((rect.Height - sf.Height) / 2.0f).RoundEx(), xOffset, yOffSet);
}
///
/// 绘制字体图片
///
/// GDI绘图
/// 字符
/// 大小
/// 颜色
/// 左
/// 上
/// 左右偏移
/// 上下偏移
public static void DrawFontImage(this Graphics graphics, int symbol, int symbolSize, Color color,
float left, float top, int xOffset = 0, int yOffSet = 0)
{
//字体
Font font = GetFont(symbol, symbolSize);
if (font == null)
{
return;
}
var symbolValue = GetSymbolValue(symbol);
string text = char.ConvertFromUtf32(symbolValue);
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
graphics.DrawString(text, font, color, left + xOffset, top + yOffSet);
graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
graphics.InterpolationMode = InterpolationMode.Default;
}
///
/// 创建图片
///
/// 字符
/// 大小
/// 颜色
/// 图片
public static Image CreateImage(int symbol, int size, Color color)
{
Bitmap image = new Bitmap(size, size);
using (Graphics g = image.Graphics())
{
SizeF sf = g.GetFontImageSize(symbol, size);
g.DrawFontImage(symbol, size, color, (image.Width - sf.Width) / 2.0f, (image.Height - sf.Height) / 2.0f);
}
return image;
}
///
/// 获取字体
///
/// 字符
/// 大小
/// 字体
public static Font GetFont(int symbol, int imageSize)
{
var symbolType = GetSymbolType(symbol);
var symbolValue = GetSymbolValue(symbol);
switch (symbolType)
{
case UISymbolType.FontAwesomeV4:
if (symbol > 0xF000)
return FontAwesomeV4.GetFont(symbolValue, imageSize);
else
return ElegantIcons.GetFont(symbolValue, imageSize);
case UISymbolType.FontAwesomeV5Brands:
return FontAwesomeV5Brands.GetFont(symbolValue, imageSize);
case UISymbolType.FontAwesomeV5Regular:
return FontAwesomeV5Regular.GetFont(symbolValue, imageSize);
case UISymbolType.FontAwesomeV5Solid:
return FontAwesomeV5Solid.GetFont(symbolValue, imageSize);
default:
if (symbol > 0xF000)
return FontAwesomeV4.GetFont(symbolValue, imageSize);
else
return ElegantIcons.GetFont(symbolValue, imageSize);
}
}
}
///
/// 字体图标图片
///
public class FontImages
{
private readonly PrivateFontCollection ImageFont;
private readonly Dictionary Fonts = new Dictionary();
private const int MinFontSize = 8;
private const int MaxFontSize = 88;
private readonly IntPtr memoryFont = IntPtr.Zero;
public FontImages(byte[] buffer)
{
ImageFont = new PrivateFontCollection();
memoryFont = Marshal.AllocCoTaskMem(buffer.Length);
Marshal.Copy(buffer, 0, memoryFont, buffer.Length);
ImageFont.AddMemoryFont(memoryFont, buffer.Length);
Loaded = true;
LoadDictionary();
}
///
/// 构造函数
///
/// 字体文件名
public FontImages(string filename)
{
if (File.Exists(filename))
{
ImageFont = new PrivateFontCollection();
ImageFont.AddFontFile(filename);
Loaded = true;
LoadDictionary();
}
}
///
/// 字体加载完成标志
///
public bool Loaded
{
get;
}
private void LoadDictionary()
{
int size = MinFontSize;
for (int i = 0; i <= MaxFontSize - MinFontSize; i++)
{
Fonts.Add(size, GetFont(size));
size += 1;
}
}
///
/// 析构函数
///
~FontImages()
{
foreach (var font in Fonts.Values)
{
font.Dispose();
}
if (memoryFont != IntPtr.Zero)
{
Marshal.FreeCoTaskMem(memoryFont);
}
Fonts.Clear();
}
///
/// 获取字体
///
/// 图标
/// 图标大小
/// 字体
public Font GetFont(int iconText, int imageSize)
{
int item = GetFontSize(iconText, imageSize);
if (Fonts.ContainsKey(item))
{
return Fonts[GetFontSize(iconText, imageSize)];
}
return null;
}
///
/// 获取字体大小
///
/// 图标
/// 图标大小
/// 字体大小
public int GetFontSize(int symbol, int imageSize)
{
using (Bitmap bitmap = new Bitmap(48, 48))
using (Graphics graphics = Graphics.FromImage(bitmap))
{
return BinarySearch(graphics, MinFontSize, MaxFontSize, symbol, imageSize);
}
}
public int BinarySearch(Graphics graphics, int low, int high, int symbol, int imageSize)
{
int mid = (low + high) / 2;
Font font = Fonts[mid];
SizeF sf = GetIconSize(symbol, graphics, font);
if (low >= high)
{
return mid;
}
if (sf.Width < imageSize && sf.Height < imageSize)
{
return BinarySearch(graphics, mid + 1, high, symbol, imageSize);
}
return BinarySearch(graphics, low, mid - 1, symbol, imageSize);
}
private Size GetIconSize(int iconText, Graphics graphics, Font font)
{
string text = char.ConvertFromUtf32(iconText);
return graphics.MeasureString(text, font).ToSize();
}
public Icon ToIcon(Bitmap srcBitmap, int size)
{
if (srcBitmap == null)
{
throw new ArgumentNullException(nameof(srcBitmap));
}
Icon icon;
using (MemoryStream memoryStream = new MemoryStream())
{
new Bitmap(srcBitmap, new Size(size, size)).Save(memoryStream, ImageFormat.Png);
Stream stream = new MemoryStream();
BinaryWriter binaryWriter = new BinaryWriter(stream);
if (stream.Length <= 0L)
{
return null;
}
binaryWriter.Write((byte)0);
binaryWriter.Write((byte)0);
binaryWriter.Write((short)1);
binaryWriter.Write((short)1);
binaryWriter.Write((byte)size);
binaryWriter.Write((byte)size);
binaryWriter.Write((byte)0);
binaryWriter.Write((byte)0);
binaryWriter.Write((short)0);
binaryWriter.Write((short)32);
binaryWriter.Write((int)memoryStream.Length);
binaryWriter.Write(22);
binaryWriter.Write(memoryStream.ToArray());
binaryWriter.Flush();
binaryWriter.Seek(0, SeekOrigin.Begin);
icon = new Icon(stream);
stream.Dispose();
}
return icon;
}
private Font GetFont(float size)
{
return Loaded ? new Font(ImageFont.Families[0], size, FontStyle.Regular, GraphicsUnit.Point) : null;
}
}
}