SunnyUI/SunnyUI/Font/UIFontImage.cs
2020-05-18 23:25:19 +08:00

404 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
* CopyRight (C) 2012-2020 ShenYongHua(沈永华).
* QQ群56829229 QQ17612584 EMailSunnyUI@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
* 文件说明: 字体图片帮助类
* 当前版本: V2.2
* 创建日期: 2020-01-01
*
* 2020-01-01: V2.2.0 增加文件说明
******************************************************************************/
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.Windows.Forms;
namespace Sunny.UI
{
/// <summary>
/// 字体图片帮助类
/// </summary>
public static class FontImageHelper
{
/// <summary>
/// AwesomeFont
/// </summary>
public static FontImages AwesomeFont;
/// <summary>
/// ElegantFont
/// </summary>
public static FontImages ElegantFont;
/// <summary>
/// 构造函数
/// </summary>
static FontImageHelper()
{
string font = DirEx.CurrentDir() + "FontAwesome.ttf";
CreateFontFile(font, "Sunny.UI.Font.FontAwesome.ttf");
AwesomeFont = new FontImages(DirEx.CurrentDir() + "FontAwesome.ttf");
font = DirEx.CurrentDir() + "ElegantIcons.ttf";
CreateFontFile(font, "Sunny.UI.Font.ElegantIcons.ttf");
ElegantFont = new FontImages(DirEx.CurrentDir() + "ElegantIcons.ttf");
}
/// <summary>
/// 从系统资源中保存字体文件
/// </summary>
/// <param name="file">字体文件名</param>
/// <param name="resource">资源名称</param>
private static void CreateFontFile(string file, string resource)
{
if (!File.Exists(file))
{
Stream fontStream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);
if (fontStream != null)
{
byte[] buffer = new byte[fontStream.Length];
fontStream.Read(buffer, 0, (int)fontStream.Length);
fontStream.Close();
File.WriteAllBytes(file, buffer);
}
}
}
/// <summary>
/// 获取字体大小
/// </summary>
/// <param name="graphics">GDI绘图</param>
/// <param name="symbol">字符</param>
/// <param name="symbolSize">大小</param>
/// <returns>字体大小</returns>
public static SizeF GetFontImageSize(this Graphics graphics, int symbol, int symbolSize)
{
Font font = GetFont(symbol, symbolSize);
if (font == null)
{
return new SizeF(0, 0);
}
Label Image = new Label();
Image.AutoSize = true;
Image.Font = font;
Image.Text = char.ConvertFromUtf32(symbol);
Size ImageSize = Image.PreferredSize;
Image.Dispose();
return ImageSize;
}
/// <summary>
/// 绘制字体图片
/// </summary>
/// <param name="graphics">GDI绘图</param>
/// <param name="symbol">字符</param>
/// <param name="symbolSize">大小</param>
/// <param name="color">颜色</param>
/// <param name="left">左</param>
/// <param name="top">上</param>
/// <param name="xOffset">左右偏移</param>
/// <param name="yOffSet">上下偏移</param>
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;
}
string text = char.ConvertFromUtf32(symbol);
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.DrawString(text, font, color, left + xOffset, top + yOffSet);
}
/// <summary>
/// 绘制字体图片
/// </summary>
/// <param name="graphics">GDI绘图</param>
/// <param name="symbol">字符</param>
/// <param name="symbolSize">大小</param>
/// <param name="color">颜色</param>
/// <param name="rect">区域</param>
/// <param name="xOffset">左右偏移</param>
/// <param name="yOffSet">上下偏移</param>
public static void DrawFontImage(this Graphics graphics, int symbol, int symbolSize, Color color, Rectangle 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,
rect.Top + (rect.Height - sf.Height) / 2.0f, xOffset, yOffSet);
}
/// <summary>
/// 创建图片
/// </summary>
/// <param name="symbol">字符</param>
/// <param name="size">大小</param>
/// <param name="color">颜色</param>
/// <returns>图片</returns>
public static Image CreateImage(int symbol, int size, Color color)
{
Bitmap image = new Bitmap(size, size);
Graphics g = image.Graphics();
SizeF ImageSize = g.GetFontImageSize(symbol, size);
Font font = GetFont(symbol, size);
g.DrawString(char.ConvertFromUtf32(symbol), font, color, (size - ImageSize.Width) / 2.0f, (size - ImageSize.Height) / 2.0f);
return image;
}
/// <summary>
/// 获取字体
/// </summary>
/// <param name="symbol">字符</param>
/// <param name="imageSize">大小</param>
/// <returns>字体</returns>
public static Font GetFont(int symbol, int imageSize)
{
if (symbol > 0xF000)
return AwesomeFont.GetFont(symbol, imageSize);
else
return ElegantFont.GetFont(symbol, imageSize);
}
}
/// <summary>
/// 字体图标图片
/// </summary>
public class FontImages
{
private readonly PrivateFontCollection ImageFont;
private readonly Dictionary<int, Font> Fonts = new Dictionary<int, Font>();
private const int MinFontSize = 8;
private const int MaxFontSize = 43;
/// <summary>
/// 大小
/// </summary>
public int IconSize { get; set; } = 128;
/// <summary>
/// 背景色
/// </summary>
public Color BackColor { get; set; } = Color.Transparent;
/// <summary>
/// 前景色
/// </summary>
public Color ForeColor { get; set; } = Color.Black;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="filename">字体文件名</param>
public FontImages(string filename)
{
if (File.Exists(filename))
{
ImageFont = new PrivateFontCollection();
ImageFont.AddFontFile(filename);
Loaded = true;
LoadDictionary();
}
}
/// <summary>
/// 字体加载完成标志
/// </summary>
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;
}
}
/// <summary>
/// 析构函数
/// </summary>
~FontImages()
{
foreach (var font in Fonts.Values)
{
font.Dispose();
}
Fonts.Clear();
}
/// <summary>
/// 获取图标
/// </summary>
/// <param name="iconText">序号</param>
/// <param name="imageSize">图标大小</param>
/// <returns>图标</returns>
public Icon GetIcon(int iconText, int imageSize)
{
Bitmap image = GetImage(iconText, imageSize);
return image != null ? ToIcon(image, IconSize) : null;
}
/// <summary>
/// 获取字体
/// </summary>
/// <param name="iconText">图标</param>
/// <param name="imageSize">图标大小</param>
/// <returns>字体</returns>
public Font GetFont(int iconText, int imageSize)
{
return Fonts[GetFontSize(iconText, imageSize)];
}
/// <summary>
/// 获取字体大小
/// </summary>
/// <param name="iconText">图标</param>
/// <param name="imageSize">图标大小</param>
/// <returns>字体大小</returns>
public int GetFontSize(int iconText, int imageSize)
{
int size = MaxFontSize;
using (Bitmap bitmap = new Bitmap(48, 48))
using (Graphics graphics = Graphics.FromImage(bitmap))
{
for (int i = 0; i <= (MaxFontSize - MinFontSize); i++)
{
Font font = Fonts[size];
SizeF sf = GetIconSize(iconText, graphics, font);
if (sf.Width < imageSize && sf.Height < imageSize)
{
break;
}
size -= 1;
}
}
return size;
}
/// <summary>
/// 获取图片
/// </summary>
/// <param name="iconText">图标</param>
/// <param name="imageSize">图标大小</param>
/// <returns>图片</returns>
public Bitmap GetImage(int iconText, int imageSize)
{
Font imageFont = Fonts[MinFontSize];
SizeF textSize = new SizeF(imageSize, imageSize);
using (Bitmap bitmap = new Bitmap(48, 48))
using (Graphics graphics = Graphics.FromImage(bitmap))
{
int size = MaxFontSize;
for (int i = 0; i <= MaxFontSize - MinFontSize; i++)
{
Font font = Fonts[size];
SizeF sf = GetIconSize(iconText, graphics, font);
if (sf.Width < imageSize && sf.Height < imageSize)
{
imageFont = font;
textSize = sf;
break;
}
size -= 1;
}
}
Size iconSize = textSize.ToSize();
Bitmap srcImage = new Bitmap(iconSize.Width, iconSize.Height);
using (Graphics graphics = Graphics.FromImage(srcImage))
{
string s = char.ConvertFromUtf32(iconText);
graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
//graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
//graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawString(s, imageFont, ForeColor, new PointF(0.0f, 0.0f));
}
Bitmap result = new Bitmap(imageSize, imageSize);
using (Graphics graphics = Graphics.FromImage(result))
{
graphics.DrawImage(srcImage, imageSize / 2.0f - textSize.Width / 2.0f, imageSize / 2.0f - textSize.Height / 2.0f);
}
srcImage.Dispose();
return result;
}
private Size GetIconSize(int iconText, Graphics graphics, Font font)
{
string text = char.ConvertFromUtf32(iconText);
return graphics.MeasureString(text, font).ToSize();
}
private 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;
}
}
}