【SkiaSharp绘图08】SKPaint方法:自动换行、是否乱码、字符偏移、边界、截距、文本轮廓、测量文本

文章目录

  • 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);
}

BreakText自动换行

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);
}

判断指定的字体是否会显示乱码。
ContainsGlyphs

GetGlyphOffsets 字符偏移量

public float[] GetGlyphOffsets (string text, float origin = 0);//origin相对起始偏移

用于获取给定文本中每个字形的偏移量。这对于在进行复杂的文本布局时非常有用,因为它允许您精确控制每个字形的位置,而不仅仅是使用默认的字符间距和行间距。

获取一句文本中每个字符的偏移量,并在字符前画一竖线。
GetGlyphOffsets

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绘制文本红色描边轮廓。

GetTextPath

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);}

测量相同文本、两种字体的宽度和边界矩形,并在文字四边绘制边界矩形。

MeasureText
使用场景

  1. 自动换行

    • 根据测量的文本宽度决定何时换行,以适应固定宽度的文本容器。
  2. 对齐和布局

    • 根据测量结果调整文本的位置,实现文本的居中对齐、左对齐或右对齐。
  3. 文本容器调整

    • 根据文本宽度动态调整文本容器的大小或位置,确保文本能够正确显示。

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,你可以为绘制的内容添加丰富的视觉效果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/857076.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CVPR 2024第三弹:李飞飞教授惊喜亮相,CVPR之家乐队火爆演奏惊艳全场

CVPR 2024第三弹&#xff1a;小编与李飞飞教授惊喜同框&#xff0c;"CVPR之家"乐队火爆演奏惊艳全场&#xff01; 会议之眼 快讯 2024 年 CVPR &#xff08;Computer Vision and Pattern Recogntion Conference) 即国际计算机视觉与模式识别会议&#xff0c;于6月1…

电脑ai写作软件,4款实用的软件!

在数字化时代&#xff0c;AI写作软件已经成为创作者们不可或缺的工具。它们利用先进的自然语言处理技术和大数据分析&#xff0c;能够快速生成高质量的文章&#xff0c;大大提升了创作效率。那么&#xff0c;市面上有哪些值得一试的电脑AI写作软件呢&#xff1f;让我们一起来盘…

mongodb嵌套聚合

db.order.aggregate([{$match: {// 下单时间"createTime": {$gte: ISODate("2024-05-01T00:00:00Z"),$lte: ISODate("2024-05-31T23:59:59Z")}// 商品名称,"goods.productName": /美国皓齿/,//订单状态 2:待发货 3:已发货 4:交易成功…

“神刊”CA再回巅峰!2024年JCR正式发布,共21848本期刊,附完整版EXCEL版下载!

2024 年 6 月 20 日&#xff0c;科睿唯安&#xff08;Clarivate Analytics&#xff09;发布了最新的《期刊引证报告》(Journal Citation Reports&#xff0c;JCR&#xff09;&#xff0c;以下简要介绍最新影响因子&#xff08;IF&#xff09;情况&#xff1a; 2023年完整版JCR…

容器之工具栏构件演示

代码; #include <gtk-2.0/gtk/gtk.h> #include <glib-2.0/glib.h> #include <gtk-2.0/gdk/gdkkeysyms.h> #include <stdio.h>int main(int argc, char *argv[]) {gtk_init(&argc, &argv);GtkWidget *window;window gtk_window_new(GTK_WINDO…

[Qt]Qt框架解析:从入门到精通,探索平台开发的无限可能

一、Qt的概述 Qt是一个跨平台的C图形用户界面应用程序框架&#xff08;GUI&#xff09;。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的&#xff0c;很容易扩展&#xff0c;并且允许真正的组件编程。开发环境为Qt creator5.8.0&#xff0c;下载…

项目经验——交通行业数据可视化大屏、HMI设计

交通行业数据大屏、HMI设计时要的注意点&#xff1a;清晰可读、简洁直观、适配性强。颜色对比度满足WCAG标准&#xff0c;深色背景减少干扰&#xff0c;实时展示交通数据&#xff0c;支持有线网络控制内容更新&#xff0c;保障驾驶安全与决策效率。

通过“BOSS”精通比特币,深入认识私钥、账户和钱包

来源:币界原创 作者:636Marx 无论当今数字货币技术如何发展&#xff0c;认识区块链技术幕后的关键机制至关重要。无论您是新手还是经验丰富的数字货币从业者&#xff0c;掌握钱包地址、公钥和私钥的复杂性都有无可替代重要性。进入 BOSS Wallet&#xff0c;这是一款尖端的 Web…

ICMAN触摸芯片——防水触摸

ICMAN触摸芯片之防水触摸触摸按键控制开关和调节挡位和切换不同模式 淋水状态下&#xff0c;触摸按键反应灵敏&#xff0c;不误触发&#xff0c; ICMAN触摸芯片稳定性与抗干扰能力强&#xff0c; 可以轻松解决家电触摸感应不灵敏和有水误触发的问题&#xff0c; 从而有效实…

Linux_文件IO

目录 一、库函数进行文件操作 1、fopen/fclose 2、fwrite 3、追加方式-“a” 4、fread 5、三个默认文件流 二、系统函数进行文件操作 1、open/close 2、write 3、追加方式-“O_APPEND” 4、read 5、struct file结构体 6、文件描述符 6.1 struct file的引用…

中学理化生实验室建设及配置要求

在中学物理、化学、生物等学科教学中&#xff0c;实验占据了非常重要的地位&#xff0c;是整个教学过程中不可或缺的部分。很多理科教学需要在实验室完成演示和学习任务&#xff0c;实验室也是保证教学计划得以实施的物质基础。因此&#xff0c;中学理化生实验室建设标准与否&a…

【C++ | const成员】类的 const数据成员、const成员函数、const对象、mutable 数据成员

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-06-14 2…

win10修改远程桌面端口号,在Windows 10中修改远程桌面端口号的步骤

在Windows 10中&#xff0c;远程桌面服务&#xff08;Remote Desktop Services, RDS&#xff09;允许用户从远程位置访问和操作计算机。默认情况下&#xff0c;远程桌面协议&#xff08;RDP&#xff09;使用端口3389进行通信。然而&#xff0c;出于安全考虑&#xff0c;管理员可…

VScode创建ROS项目 ROS集成开发环境

ROS使用VScode创建项目步骤 1.创建ROS工作空间2.启动VScode3.VScode编译ROS4.创建ROS功能包C语言开发Python语言开发 本文章介绍了如何在Ubuntu18.04系统下搭建VScode 的ROS项目 搭建项目分为一下几个步骤&#xff1a; 1.创建ROS工作空间 创建一个demo的ROS工作空间&#xff0…

大数据学习-Hadoop

介绍 是 Apache 的顶级开源项目&#xff0c;一个分布式框架&#xff0c;主要功能&#xff1a; 分布式大数据存储——HDFS 组件分布式大数据计算——MapReduce 组件分布式资源调度——YARN 组件 可以通过它来构建集群&#xff0c;完成大数据的存储和计算 学习起来相对简单&…

怎么看电脑实时充电功率

因为我想测试不同的充电器给电脑充电的速度&#xff0c;所以就想找一款软件可以看电脑当前充电功率的软件&#xff0c;我给一个图 直接搜索就可以下载了&#xff0c;charge rate就是功率&#xff0c;这里是毫瓦&#xff0c;换算单位是 1000mw1w 所以我这里充电功率是65w&…

6.21 移动语义与智能指针

//先构造&#xff0c;再拷贝构造//利用"hello"这个字符串创建了一个临时对象//并复制给了s3//这一步实际上new了两次String s3 "hello"; 背景需求&#xff1a; 这个隐式创建的字符串出了该行就直接销毁掉&#xff0c;效率比较低 可以让_pstr指向这个空间…

squareline studio浅尝(1)在对话框添加键盘

因项目需要&#xff0c;需要修改IP地址等参数&#xff0c;需要编辑文本对话框内容&#xff0c;这时候就需要调用键盘&#xff0c;操作如下。主要为了做笔记。如有误导请及时留言。 1&#xff09;拖一个键盘到对话框页面。默认把它隐藏&#xff08;flag:hidden&#xff09; 2&…

想更好应对突发网络与业务问题?您需要一款“全流量”

全流量分析&#xff0c;能为我做什么&#xff1f; 在生活中遇到问题&#xff0c;我们的第一反应可能是拿出手机拍照记录&#xff0c;方便后续处理。这些问题是临时的、突发的。 流量分析&#xff0c;就是网络中的“手机”&#xff0c;针对突发的网络故障和安全事件&#xff0…

课程管理系统

摘 要 在大学里&#xff0c;课程管理是一件非常重要的工作&#xff0c;教学工作人员每天都要与海量的数据和信息打交道。确保数据的精确度和完整程度&#xff0c;影响着每一位同学的学习、生活和各种活动的正常展开&#xff0c;更合理的信息管理也为高校工作的正规化运行和规范…