【SkiaSharp绘图07】SKPaint详解(五)IsAntialias/IsStroke/Style/StrokeCap/StrokeJoin/StrokeMiter/TextAlign

SKPaint属性详解

IsAntialias 是否抗锯齿

public bool IsAntialias { get; set; }//默认:false

获取或设置是否抗锯齿。

IsAutohinted 是否启用自动提示

public bool IsAutohinted { get; set; }//默认:false

用于指示文本是否启用了自动提示(autohinting)。自动提示是一种字形渲染技术,旨在通过微调字形轮廓来改善小字号文本的显示效果,特别是在低分辨率设备上,例如显示器或移动设备。
作用与意义

  1. 改善小字号文本的清晰度

    • 在小字号文本渲染时,启用自动提示可以帮助保持字形的清晰度和可读性。通过微调字形的轮廓,使得字符在低分辨率设备上的显示效果更加平滑和清晰。
  2. 适应不同的显示设备

    • 自动提示可以根据不同的显示设备(如高分辨率和低分辨率)来调整字形的渲染方式,以优化显示效果。在低分辨率设备上特别有用,因为它可以弥补分辨率限制带来的字形失真问题。
  3. 控制渲染行为

    • 通过控制 IsAutohinted 属性,开发人员可以选择启用或禁用自动提示功能,以根据特定的应用需求和目标设备选择最合适的字体渲染方式。

IsDither 是否应用抖动

public bool IsDither { get; set; }//默认:false

控制是否应用抖动(dithering)效果。抖动是一种在颜色深度降低时,通过随机或有序地混合颜色来模拟更多颜色的技术,目的是减少颜色带状条纹(banding)现象,提升图像的视觉质量。

作用和效果

  1. 减少颜色带状条纹

    • 主要作用是在颜色深度较低的情况下,通过混合相邻的颜色值,使得过渡更加平滑,减少颜色之间的明显边界,从而减少颜色带状条纹的出现。
  2. 提升图像的视觉质量

    • 尤其是在渐变和细节丰富的图像中,启用抖动可以使颜色过渡更加自然,使得图像看起来更加平滑和真实,避免了单调的颜色块效果。
  3. 适应不同显示设备

    • 特别是在低分辨率显示设备上,启用抖动可以显著改善图像的表现,因为低分辨率设备往往难以显示复杂的颜色过渡。

IsEmbeddedBitmapText 是否启用嵌入式位图文本渲染

public bool IsEmbeddedBitmapText { get; set; }//默认:false

文本渲染通常可以使用矢量文本或嵌入式位图文本两种方式:

  1. 矢量文本:使用矢量图形方式绘制的文本,其优势在于可以无限缩放而不失真,适用于各种分辨率的显示设备。

  2. 嵌入式位图文本:使用预先渲染好的位图字形来显示文本,每个字形以位图形式存储。相比于矢量文本,嵌入式位图文本在显示时可以更快速,但是缩放时可能会失真或显示不清晰,特别是在高分辨率设备上。

作用与效果

  • 作用SKPaint.IsEmbeddedBitmapText 控制 SkiaSharp 是否使用嵌入式位图文本渲染文本。

  • 效果

    • 启用嵌入式位图文本:如果将 IsEmbeddedBitmapText 设置为 true,SkiaSharp 将尝试使用嵌入式位图来渲染文本。这通常会导致文本在绘制时速度更快,特别是在一些需要频繁绘制文本的场景中。
    • 禁用嵌入式位图文本:如果将 IsEmbeddedBitmapText 设置为 false,SkiaSharp 将使用矢量方式来渲染文本。这种方式下,文本可以实现无损缩放和更高的显示精度,但可能会牺牲一些绘制速度。

IsLinearText 是否启用线性文本

public bool IsLinearText { get; set; }//默认:true

文本渲染可以使用两种方式:线性文本和非线性文本。

  1. 线性文本:默认情况下,SkiaSharp 使用线性文本渲染。线性文本渲染意味着无论文本的绘制变换如何,文本的水平和垂直方向的线性度(Linear)保持不变。这种方式适用于大多数情况,能够保证文本的垂直和水平线条都是直的。

  2. 非线性文本:在某些情况下,可能需要使用非线性文本渲染。非线性文本允许文本在垂直和水平方向上进行某些变形,例如斜体文字,或者在旋转的情况下保持更加自然的外观。

**作用与效果 **

  • 作用SKPaint.IsLinearText 控制文本是否使用线性文本渲染方式。

  • 效果

    • 启用线性文本:如果将 IsLinearText 设置为 true,则文本将使用线性方式进行渲染。这种方式下,文本的水平和垂直线条将始终保持直线,不受文本绘制变换的影响。
    • 禁用线性文本:如果将 IsLinearText 设置为 false,SkiaSharp 将使用非线性文本渲染方式。这使得文本在某些情况下可以更加自然,例如在旋转或倾斜文本时,可以保持更加逼真的外观。

IsStroke 是否只描边

public bool IsStroke { get; set; }//默认:false

获取或设置,文本是否只描边或填充。

LcdRenderText 是否启用LCD显示器渲染方式

public bool LcdRenderText { get; set; }//默认:false

用于控制文本在 LCD 显示器上的渲染方式。
LCD(Liquid Crystal Display)液晶显示器通常由像素阵列组成,每个像素包含红、绿、蓝三个子像素。在文本渲染过程中,有时需要特别处理文本以适应 LCD 显示器的特性,以减少边缘锯齿和提升显示质量。

作用与效果

  • 作用SKPaint.LcdRenderText 控制文本在 LCD 显示器上的渲染方式。

  • 效果

    • 启用 LCD 渲染:如果将 LcdRenderText 设置为 true,SkiaSharp 将使用特定的文本渲染算法来适应 LCD 显示器。这种方式下,文本在 LCD 显示器上通常会显示得更加清晰,边缘锯齿也会得到一定程度的抑制。
    • 禁用 LCD 渲染:如果将 LcdRenderText 设置为 false,SkiaSharp 将使用传统的文本渲染方式,可能会在 LCD 显示器上显示出较为明显的边缘锯齿。

Style 描边、填充样式

public SkiaSharp.SKPaintStyle Style { get; set; }

获取或设置文本、图形的描边和填充样式。

相关代码示例

/// <summary>
/// 绘制文本与图像
/// </summary>
/// <param name="text"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="paint"></param>
/// <param name="canvas"></param>
/// <param name="next"></param>
private void DrawBmpAndTip(string text, ref float x, ref float y, SKPaint paint, SKCanvas canvas, bool next = false)
{
    canvas.DrawText(text, x, y, paint);
    const float imgWidth = 200;
    canvas.DrawBitmap(skBmp, new SKRect(x, y + 10, x + imgWidth, y + 10 + imgWidth), paint);
    x += imgWidth + 20;
    if (next)
    {
        y += imgWidth + paint.FontSpacing;
        x = 10;
    }
}
var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

if (skBmp == null) skBmp = SKBitmap.Decode(@"Images\AIWoman.png");

using (var paint = new SKPaint())
{
    paint.TextSize = 24;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
    paint.Color = SKColors.Red;

    float x = 10;
    float y = 20;

    paint.IsAntialias = true;
    DrawBmpAndTip($"IsAntialias:{paint.IsAntialias}", ref x, ref y, paint, canvas, false);
    paint.IsAntialias = false;
    DrawBmpAndTip($"IsAntialias:{paint.IsAntialias}", ref x, ref y, paint, canvas, false);

    paint.IsAutohinted = true;
    DrawBmpAndTip($"IsAutohinted:{paint.IsAutohinted}", ref x, ref y, paint, canvas, false);
    paint.IsAutohinted = false;
    DrawBmpAndTip($"IsAutohinted:{paint.IsAutohinted}", ref x, ref y, paint, canvas, true);

    paint.IsDither = true;
    DrawBmpAndTip($"IsDither:{paint.IsDither}", ref x, ref y, paint, canvas, false);
    paint.IsDither = false;
    DrawBmpAndTip($"IsDither:{paint.IsDither}", ref x, ref y, paint, canvas, false);

    paint.IsEmbeddedBitmapText = true;
    DrawBmpAndTip($"BmpTxt:{paint.IsEmbeddedBitmapText}", ref x, ref y, paint, canvas, false);
    paint.IsEmbeddedBitmapText = false;
    DrawBmpAndTip($"BmpTxt:{paint.IsEmbeddedBitmapText}", ref x, ref y, paint, canvas, true);

    paint.IsLinearText = false;
    DrawBmpAndTip($"IsLinearText:{paint.IsLinearText}", ref x, ref y, paint, canvas, false);
    paint.IsLinearText = true;
    DrawBmpAndTip($"IsLinearText:{paint.IsLinearText}", ref x, ref y, paint, canvas, false);

    paint.IsStroke = true;
    DrawBmpAndTip($"IsStroke:{paint.IsStroke}", ref x, ref y, paint, canvas, false);
    paint.IsStroke = false;
    DrawBmpAndTip($"IsStroke:{paint.IsStroke}", ref x, ref y, paint, canvas, true);

    paint.LcdRenderText = true;
    DrawBmpAndTip($"LcdRenderText:{paint.LcdRenderText}", ref x, ref y, paint, canvas, false);
    paint.LcdRenderText = false;
    DrawBmpAndTip($"LcdRenderText:{paint.LcdRenderText}", ref x, ref y, paint, canvas, false);

    y += paint.FontSpacing;
    paint.StrokeWidth = 1.3f;
    paint.Style = SKPaintStyle.Fill;
    canvas.DrawText($"Style:Fill", x, y, paint);
    paint.Style = SKPaintStyle.Stroke;
    canvas.DrawText($"Style:Stroke", x, y + paint.FontSpacing, paint);
    paint.Style = SKPaintStyle.StrokeAndFill;
    canvas.DrawText($"Style:StrokeAndFill", x, y + paint.FontSpacing * 2, paint);
}

对于IsAntialias、IsStroke、Style能看见明显区别,其他属性无法明显看出其效果不同之处。
SKPaint属性说解

StrokeCap线帽样式

public SkiaSharp.SKStrokeCap StrokeCap { get; set; }//默认:Butt

获取或设置描边线段的起止点的样式。(应用于非闭合轮廓的开头与结尾)

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.Style = SKPaintStyle.Stroke;
    paint.Color = SKColors.LightGreen;
    paint.StrokeWidth = 20;
    paint.IsAntialias = true;
    paint.TextSize = 18;

    paint.StrokeCap = SKStrokeCap.Butt;
    canvas.DrawLine(50, 50, 50, 150, paint);

    paint.StrokeCap = SKStrokeCap.Round;
    canvas.DrawLine(250, 50, 250, 150, paint);

    paint.StrokeCap = SKStrokeCap.Square;
    canvas.DrawLine(450, 50, 450, 150, paint);

    paint.StrokeWidth = 1;
    paint.Color = SKColors.Red;
    canvas.DrawLine(10, 50, 500, 50, paint);
    canvas.DrawText($"StrokeCap:Butt", 50, 30, paint);
    canvas.DrawText($"StrokeCap:Round", 250, 30, paint);
    canvas.DrawText($"StrokeCap:Square", 450, 30, paint);
}

绘制三段相同高度的线段,观察不同样式的线帽与长度。
StrokeCap

StrokeJoin 连接样式

public SkiaSharp.SKStrokeJoin StrokeJoin { get; set; }//默认:Miter

获取或设置线段连接的类型。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.Style = SKPaintStyle.Stroke;
    paint.Color = SKColors.LightGreen;
    paint.StrokeWidth = 20;
    paint.IsAntialias = true;
    paint.TextSize = 18;

    paint.StrokeJoin = SKStrokeJoin.Miter;
    canvas.DrawRect(50, 50, 100, 100, paint);

    paint.StrokeJoin = SKStrokeJoin.Round;
    canvas.DrawRect(250, 50, 100, 100, paint);

    paint.StrokeJoin = SKStrokeJoin.Bevel;
    canvas.DrawRect(450, 50, 100, 100, paint);

    paint.StrokeWidth = 1;
    paint.Color = SKColors.Red;
    canvas.DrawText($"StrokeJoin:Miter", 50, 30, paint);
    canvas.DrawText($"StrokeJoin:Round", 250, 30, paint);
    canvas.DrawText($"StrokeJoin:Bevel", 450, 30, paint);
}

StrokeJoin

StrokeMiter 斜接限制

public float StrokeMiter { get; set; }

用于控制描边(stroke)拐角的斜接(miter)长度。它在绘制折线或多边形时特别重要,因为它影响线条拐角的外观。

 var canvas = e.Surface.Canvas;
 var info = e.Info;
 canvas.Clear(SKColors.White);

 using (var paint = new SKPaint())
 {
     paint.Style = SKPaintStyle.Stroke;
     paint.Color = SKColors.LightGreen;
     paint.StrokeWidth = 50;
     paint.IsAntialias = true;
     paint.TextSize = 18;

     // 创建路径
     var path = new SKPath();
     var xOffset = 500;
     path.MoveTo(20, 80);
     path.LineTo(20+xOffset, 100);
     path.LineTo(20, 120);


     paint.StrokeJoin = SKStrokeJoin.Miter;
     paint.StrokeMiter = 100;
     paint.Color = new SKColor(255, 0, 0, 127);
     canvas.DrawPath(path, paint);
     

     paint.StrokeMiter = 50;
     paint.StrokeWidth = 15;
     paint.Color = new SKColor(0, 255, 0, 127);
     canvas.DrawPath(path, paint);

     paint.StrokeMiter = 15;
     paint.StrokeWidth = 15;
     paint.Color = new SKColor(0, 0, 255, 127);
     canvas.DrawPath(path, paint);
 }

不同的StrokeMiter效果(一般只能控制尖或不尖,要控制在中间位置,我是没成功过)
StrokeMiter

SubpixelText 是否启用亚像素定位

public bool SubpixelText { get; set; }

用于控制文本渲染是否使用亚像素定位(subpixel positioning)。

  • 整像素定位(Whole Pixel Positioning):在整像素定位中,文本的字符位置被限制在像素边界上,这样可能会导致文本的排列不够精确,特别是在小字体或精细排版时,可能会显得不够平滑。

  • 亚像素定位(Subpixel Positioning):在亚像素定位中,文本的字符位置可以在像素内部的任意位置,这使得字符之间的间距可以更加精确,从而提高文本的可读性和排版质量,特别是在小字号和高分辨率显示器上效果更明显。

  • 作用SKPaint.SubpixelText 控制是否启用亚像素定位来渲染文本。

  • 效果

    • 启用亚像素定位:如果将 SubpixelText 设置为 true,SkiaSharp 将使用亚像素定位来渲染文本。这将使文本显示更加平滑和清晰,尤其在小字体和高分辨率屏幕上效果更为明显。
    • 禁用亚像素定位:如果将 SubpixelText 设置为 false,SkiaSharp 将使用整像素定位来渲染文本。这可能会导致文本在某些情况下看起来不够平滑,特别是在小字体和低分辨率屏幕上。

TextAlign文本对齐方式

public SkiaSharp.SKTextAlign TextAlign { get; set; }//默认:Left

获取或设置文本对齐方式。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{                
    paint.IsAntialias = true;
    paint.TextSize = 48;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

    paint.TextAlign = SKTextAlign.Left;
    paint.Color = SKColors.Red;
    canvas.DrawText("Left", 400, 100, paint);

    paint.TextAlign = SKTextAlign.Center;
    paint.Color = SKColors.Green;
    canvas.DrawText("Center", 400, 150, paint);

    paint.TextAlign = SKTextAlign.Right;
    paint.Color = SKColors.Blue;
    canvas.DrawText("Right", 400, 200, paint);

    canvas.DrawLine(400, 50, 400, 250, paint);             
}

绘制一x偏移坐标相同,观察不同对齐方式,线段为绘制垂直基线。
TextAlign

TextEncoding 文本编码

public SkiaSharp.SKTextEncoding TextEncoding { get; set; }//默认:utf8

指定 SKPaint 实例处理和渲染文本时所采用的文本编码方式。不同的编码方式会直接影响文本数据的解释和呈现。
影响

  1. 文本解析
    根据 SKPaint.TextEncoding 的设置,SkiaSharp 将以不同的方式解析输入的文本数据。例如,UTF-8 编码的数据将按照 UTF-8 的规则进行解析,而 GlyphID 编码的数据将直接被解释为字形索引。

  2. 字符渲染
    解析后的文本数据会影响最终渲染的字符。正确的编码设置可以确保文本被正确地转换为相应的字形,从而避免出现乱码或错误的字符。

  3. 性能
    不同的编码方式可能对性能产生影响。比如,UTF-32 每个字符固定占用 4 个字节,解析较为简单,但内存占用较大;而 UTF-8 对 ASCII 字符比较高效,但对非 ASCII 字符需要多字节编码,解析稍复杂。

TextScaleX 文本水平比例因子

public float TextScaleX { get; set; }//默认:1

获取或设置绘制文本的水平比例因子。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.TextSize = 48F;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

    var yOffset = paint.TextSize;
    var scales = new float[] { 0.5F, 1F, 2F };
    foreach (var value in scales)
    {
        paint.TextScaleX = value;
        canvas.DrawText($"SkiaSharp绘图,TextScaleX:{value}", 20, yOffset, paint);
        yOffset += paint.FontSpacing;
    }
}

分别以0.5、1、2倍比例,绘制相同文本。
TextScaleX

TextSkewX 水平倾斜系数

public float TextSkewX { get; set; }//默认:0

获取和设置文本水平倾斜系数,小于0向右倾,大于0向左倾。

var canvas = e.Surface.Canvas;
var info = e.Info;
canvas.Clear(SKColors.White);

using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.TextSize = 48F;
    paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");

    var yOffset = paint.TextSize;
    var scales = new float[] { -1F,0F,1F};
    foreach (var value in scales)
    {
        paint.Color = SKColors.Black;
        paint.TextSkewX = value;
        canvas.DrawText($"SkiaSharp绘图,TextSkewX:{value}", 20, yOffset, paint);
        paint.Color = SKColors.Red;
        canvas.DrawLine(20, yOffset, info.Width, yOffset, paint);
        yOffset += paint.FontSpacing;
    }
}

在这里插入图片描述

TypeFace 字体样式

public SkiaSharp.SKTypeface Typeface { get; set; }

获取和设置绘制文本的字体样式。

paint.Typeface = SKTypeface.FromFamilyName("微软雅黑");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图南科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值