文章目录
- SKPaint方法
- BreakText 计算指定宽度内可绘制的字符个数
- ContainsGlyphs字体是否包含文本字符(是否会乱码)
- GetGlyphOffsets 字符偏移量
- GetGlyphPositions 偏移坐标
- GetGlyphWidths 每个字符的宽度与边界
- GetHorizontalTextIntercepts 轮廓截距
- GetPositionedTextIntercepts轮廓截距
- GetTextIntercepts 轮廓截距
- 代码示例
- GetTextPath 文本轮廓路径
- MeasureText 测量文本
- Reset重置
- Clone 克隆
- ToFont
- SetColor
- 其它待补充
- MaskFilter 掩码过滤器
- PathEffect 路径效果
- Shader 着色器
SKPaint方法
BreakText 计算指定宽度内可绘制的字符个数
public long BreakText (string text, float maxWidth);
public long BreakText (byte[] text, float maxWidth, out float measuredWidth);
指定要测量的文本和最大文本绘制宽度,获取指定宽度内可绘制的字符个数和实际绘制宽度。
实现一个可自动换行绘制的函数
/// <summary>
/// 绘制自动换行的文本
/// </summary>
/// <param name="canvas"></param>
/// <param name="text">待绘制的文本</param>
/// <param name="maxWidth">文本最大宽度</param>
/// <param name="left">文本框左上角X轴起始</param>
/// <param name="top">文本框左上角Y轴起始</param>
/// <param name="paint"></param>
/// <param name="endWidth">最后一行实际绘制宽度</param>
/// <returns>总文本框高度</returns>
public float DrawTextWithWordWrap(SKCanvas canvas, string text, float maxWidth,
float left, float top, SKPaint paint,out float endWidth)
{
endWidth = 0F;
if (string.IsNullOrEmpty(text)) return 0.0f;
//文本基线
float baselineY = top - paint.FontMetrics.Ascent;
while (true)
{
var breakIndex = (int)paint.BreakText(text, maxWidth, out endWidth);
string line = text.Substring(0, breakIndex);
canvas.DrawText(line, left, baselineY, paint);
text = text.Substring(breakIndex).TrimStart(); // 去掉已经绘制的部分,继续处理剩余的文本
if (!string.IsNullOrEmpty(text))
{
baselineY += paint.FontSpacing;
}
else
{
break;
}
}
return baselineY + paint.FontMetrics.Descent - top;
}
给定文本框左上角起始点、文本框宽度、文本内容。绘制后,将文本框绘制一个矩形,并在结尾位置画一蓝色竖线。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
const string TEXT = "SkiaSharp 是一个跨平台的 2D 图形库,用于 .NET 平台。它是 Skia 图形引擎的 .NET 绑定,提供了高性能的绘图和图形处理功能。SkiaSharp 允许开发人员在 .NET 平台上创建丰富的用户界面、图像处理应用程序、游戏和数据可视化工具。";
using (var paint = new SKPaint())
{
paint.IsAntialias = true;
paint.TextSize = 24;
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
var edge = 20;
var top = 50;
var txtWidth = Math.Max(30, info.Width - edge * 2);
var height = DrawTextWithWordWrap(canvas, TEXT, txtWidth, edge, top, paint,out float endWidth);
paint.Color = SKColors.Red;
paint.IsStroke = true;
//实际的文本框
canvas.DrawRect(edge, top, txtWidth, height, paint);
//文本结尾的位置
paint.Color = SKColors.Blue;
paint.StrokeWidth = 5;
canvas.DrawLine(edge + endWidth, top + height - paint.FontSpacing, edge + endWidth, top + height,paint);
}
ContainsGlyphs字体是否包含文本字符(是否会乱码)
public bool ContainsGlyphs (string text);
public bool ContainsGlyphs (byte[] text);
获取指定文本所有字符是否对应于非零字形索引(不会乱码)。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
const string TEXT = "SkiaSharp绘图";
using (var paint = new SKPaint())
{
paint.IsAntialias = true;
paint.TextSize = 24;
paint.Typeface = SKTypeface.FromFamilyName("Arial");
//无法显示中文
canvas.DrawText($"{TEXT},{paint.Typeface.FamilyName},ContainsGlyphs:{paint.ContainsGlyphs(TEXT)}",20,50,paint);
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
//可以显示中文
canvas.DrawText($"{TEXT},{paint.Typeface.FamilyName},ContainsGlyphs:{paint.ContainsGlyphs(TEXT)}", 20, 100, paint);
}
判断指定的字体是否会显示乱码。
GetGlyphOffsets 字符偏移量
public float[] GetGlyphOffsets (string text, float origin = 0);//origin相对起始偏移
用于获取给定文本中每个字形的偏移量。这对于在进行复杂的文本布局时非常有用,因为它允许您精确控制每个字形的位置,而不仅仅是使用默认的字符间距和行间距。
获取一句文本中每个字符的偏移量,并在字符前画一竖线。
GetGlyphPositions 偏移坐标
public SkiaSharp.SKPoint[] GetGlyphPositions (string text, SkiaSharp.SKPoint origin = default);
获取每个字符的偏移坐标
GetGlyphWidths 每个字符的宽度与边界
public float[] GetGlyphWidths (string text, out SkiaSharp.SKRect[] bounds);
获取每个字符占的宽度和边界。
GetHorizontalTextIntercepts 轮廓截距
public float[] GetHorizontalTextIntercepts (string text, float[] xpositions, float y, float upperBounds, float lowerBounds);
获取文本与两条平行相交的截距。(只能单字?多字时,其它坐标不知如何处理)
xpositions:为文本起始位置
y:为文本垂直的基线位置
upperBounds:上水平线
lowerBound:下水平线,这两条线表示需要测量的范围。
GetPositionedTextIntercepts轮廓截距
public float[] GetPositionedTextIntercepts (string text, SkiaSharp.SKPoint[] positions, float upperBounds, float lowerBounds);
与GetHorizontalTextIntercepts 基本相同。
GetTextIntercepts 轮廓截距
public float[] GetTextIntercepts (string text, float x, float y, float upperBounds, float lowerBounds);
获取文字与平行线的截距,有前面函数的效果基本相同。
代码示例
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
const string TEXT = "SkiaSharp绘图";
using (var paint = new SKPaint())
{
paint.IsAntialias = true;
paint.TextSize = 48;
paint.TextScaleX = 1F;
var startX = 20F;
var startY = 100F;
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
canvas.DrawText($"{TEXT}", startX, startY, paint);
//x偏移量
var xOffsets = paint.GetGlyphOffsets(TEXT, startX);
paint.Color = SKColors.Red;
foreach(var x in xOffsets)
{
canvas.DrawLine(x, 80, x, 100, paint);
}
//x偏移量
var points = paint.GetGlyphPositions(TEXT, new SKPoint(startX, startY));
paint.Color = SKColors.Blue;
foreach (var pt in points)
{
canvas.DrawLine(pt.X, pt.Y, pt.X, pt.Y + 20, paint);
}
startY += 100;
canvas.DrawText($"{TEXT}", startX, startY, paint);
//宽度与边界
var widths = paint.GetGlyphWidths(TEXT, out SKRect[] bounds);
paint.Color = SKColors.Red;
float offsetX = startX;
paint.IsStroke= true;
var index = 0;
foreach(var rect in bounds)
{
//绘制边界矩形
canvas.DrawRect(offsetX + rect.Left, rect.Top + startY, rect.Width, rect.Height, paint);
offsetX += widths[index++];
}
// 指定文本的起始 X 坐标数组
float[] xpositions = { 100 };
// 文本的起始 Y 坐标
float y = 350;
// 指定测量区域的上边界和下边界 Y 坐标
float upperBounds = 280;
float lowerBounds = 340;
paint.TextSize = 120;
// 获取文本的水平截距
float[] intercepts = paint.GetHorizontalTextIntercepts("心", xpositions, y, upperBounds, lowerBounds);
// 绘制文本
canvas.DrawText("心", xpositions[0], y, paint);
paint.TextSize = 24;
canvas.DrawText("GetHorizontalTextIntercepts", xpositions[0] + 250, y-30, paint);
paint.TextSize = 120;
//两条水平线
paint.Color = SKColors.Green;
canvas.DrawLine(0, upperBounds, info.Width, upperBounds, paint);
canvas.DrawLine(0, lowerBounds, info.Width, lowerBounds, paint);
// 绘制截距线
paint.Color = SKColors.Red;
paint.StrokeWidth = 2;
foreach (var intercept in intercepts)
{
canvas.DrawLine(intercept, upperBounds, intercept, lowerBounds, paint);
}
y += 100;
upperBounds += 100;
lowerBounds += 100;
var skpoints = new SKPoint[] { new SKPoint(xpositions[0], y) };
intercepts = paint.GetPositionedTextIntercepts("心", skpoints, upperBounds, lowerBounds);
// 绘制文本
canvas.DrawText("心", xpositions[0], y, paint);
paint.TextSize = 24;
canvas.DrawText("GetPositionedTextIntercepts", xpositions[0] + 250, y - 30, paint);
paint.TextSize = 120;
//两条水平线
paint.Color = SKColors.Green;
canvas.DrawLine(0, upperBounds, info.Width, upperBounds, paint);
canvas.DrawLine(0, lowerBounds, info.Width, lowerBounds, paint);
// 绘制截距线
paint.Color = SKColors.Red;
paint.StrokeWidth = 2;
foreach (var intercept in intercepts)
{
canvas.DrawLine(intercept, upperBounds, intercept, lowerBounds, paint);
}
y += 100;
upperBounds += 100;
lowerBounds += 100;
intercepts = paint.GetTextIntercepts("心", xpositions[0],y, upperBounds, lowerBounds);
// 绘制文本
canvas.DrawText("心", xpositions[0], y, paint);
paint.TextSize = 24;
canvas.DrawText("GetTextIntercepts", xpositions[0] + 250, y - 30, paint);
paint.TextSize = 120;
//两条水平线
paint.Color = SKColors.Green;
canvas.DrawLine(0, upperBounds, info.Width, upperBounds, paint);
canvas.DrawLine(0, lowerBounds, info.Width, lowerBounds, paint);
// 绘制截距线
paint.Color = SKColors.Red;
paint.StrokeWidth = 2;
foreach (var intercept in intercepts)
{
canvas.DrawLine(intercept, upperBounds, intercept, lowerBounds, paint);
}
}
运行结果示例
GetTextPath 文本轮廓路径
public SkiaSharp.SKPath GetTextPath (string text, float x, float y);
public SkiaSharp.SKPath GetTextPath (string text, SkiaSharp.SKPoint[] points);
用于生成给定文本的路径数据。路径数据包含文本的轮廓信息,可以用于高级文本渲染和图形操作,例如自定义文本效果、路径动画、变形、剪切等。通过这个方法,开发者可以获取文本的几何形状,并将其用于各种自定义绘制操作。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
const string TEXT = "SkiaSharp绘图";
using (var paint = new SKPaint())
{
paint.IsAntialias = true;
paint.TextSize = 96;
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
var x = 20F;
var y = 100F;
canvas.DrawText(TEXT, x,y, paint);
//文本轮廓路径
var textPath = paint.GetTextPath(TEXT,x,y);
paint.StrokeWidth = 2;
paint.IsStroke = true;
paint.Color = SKColors.Red;
canvas.DrawPath(textPath, paint);
}
使用DrawText绘制填充黑色文本,再使用GetTextPath获取文本轮廓,再使用DrawPath绘制文本红色描边轮廓。
MeasureText 测量文本
public float MeasureText (string text);
public float MeasureText (string text, ref SkiaSharp.SKRect bounds);
用于测量给定文本字符串的宽度。这个方法的主要作用在于计算文本在指定字体和样式下的绘制尺寸,通常用于布局和排版,确保文本能够正确地放置在指定的绘制区域内。
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);
const string TEXT = "SkiaSharp绘图";
using (var paint = new SKPaint())
{
paint.IsAntialias = true;
paint.TextSize = 96;
paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
var x = 20F;
var y = 100F;
var rect=new SKRect();
var width = paint.MeasureText(TEXT, ref rect);
canvas.DrawText(TEXT,x,y, paint);
paint.IsStroke = true;
canvas.DrawRect(rect.Left + x, y + rect.Top, rect.Width, rect.Height, paint);
//修改字体、水平放大1.1倍
y +=200;
paint.Typeface = SKTypeface.FromFamilyName("宋体");
paint.TextScaleX = 1.1F;
paint.Color = SKColors.Red;
width = paint.MeasureText(TEXT, ref rect);
canvas.DrawText(TEXT, x, y, paint);
canvas.DrawRect(rect.Left + x, y + rect.Top, rect.Width, rect.Height, paint);
}
测量相同文本、两种字体的宽度和边界矩形,并在文字四边绘制边界矩形。
使用场景
-
自动换行:
- 根据测量的文本宽度决定何时换行,以适应固定宽度的文本容器。
-
对齐和布局:
- 根据测量结果调整文本的位置,实现文本的居中对齐、左对齐或右对齐。
-
文本容器调整:
- 根据文本宽度动态调整文本容器的大小或位置,确保文本能够正确显示。
Reset重置
public void Reset ();
重置 SKPaint 对象的所有属性到它们的默认状态。这在绘图过程中特别有用,可以确保在开始绘制新的图形或文本之前,所有的绘图设置都是清空的,从而避免意外影响之前的绘图设置。
Clone 克隆
public SkiaSharp.SKPaint Clone ();
浅拷贝SKPaint对象。
ToFont
public SkiaSharp.SKFont ToFont ();
获取SKPaint对应的SKFont
SetColor
public void SetColor (SkiaSharp.SKColorF color, SkiaSharp.SKColorSpace colorspace);
用于设置 SKPaint 对象的颜色属性,并指定颜色空间。这个方法允许你使用浮点颜色和指定的颜色空间来设置绘制操作的颜色属性。
浮点数范围(从0到1)表示RGBA分量。
其它待补充
MaskFilter 掩码过滤器
用于在绘制时应用掩码过滤效果。掩码过滤器可以对绘制的内容进行模糊处理、锐化处理、浮雕效果等特殊效果的处理。通过使用SKPaint.MaskFilter,你可以改变绘制对象的外观,增加视觉效果。
PathEffect 路径效果
用于对路径进行特殊效果处理。路径效果可以对绘制的路径进行各种转换和修改,比如虚线效果、路径的偏移效果、路径变换等。通过使用SKPaint.PathEffect,你可以增加绘制路径的复杂性和美观度。
Shader 着色器
用于创建和应用复杂的填充效果。着色器(Shader)可以用于填充形状和路径,产生渐变、图案填充、图像纹理等效果。通过使用SKPaint.Shader,你可以为绘制的内容添加丰富的视觉效果。