大海捞针 Skia(C++) 第 3 期:绘制文本

2023-11-19

前言

本期将正式给大家介绍Skia的使用。文章将涉及一个目的的多种方案多种情况。文章较长,请大家耐心阅读。

关键词:PNG图像、文件、文本、字符串、UTF8、UTF16、UTF32、编码转换、Visual Studio 设置、高级保存选项


案例

注意:接下来的案例都将使用PNG图像来存储查看绘制结果

Visual Studio 应将代码文件默认编码设置为UTF-8(建议不带BOM,即标准UTF8编码,操作教程如下:
Visual Studio 设置默认编码格式为 UTF-8 或 GB2312-80 与文件没有高级保存选项怎么显示

这里的常字符串不是专业术语,这里表达的意思是,代码中的字符串以及常量字符串。例如,我们在给一个string类付初始值时即会使用一个字符串例如"Hello, Skia!",这样的字符串是固定的,因为代码中就是这样。因此编译的程序里也一定默认这样初始化。至于常量字符串,则是指const char*

绘制代码中字符串步骤和上一期绘制"Hello, Skia!"一致,这里将详细介绍。
在绘制前,应确保你的Visual Studio项目已经配置好Skia库,具体步骤参考《大海捞针 Skia(C++) 第 1 期:Skia 环境搭建》。


绘制图像,就像画画一样,我们需要一个介质来存储我们的笔画痕迹。因而在Skia中,我们使用SkBitmap作为这个介质。

实例化一个SkBitmap

SkBitmap bitmap;

好比绘画所用的纸也有规格参数,同样,上述这个介质也需要。用于描述这个参数的类叫做SkImageInfo
我们可以通过如下方式,手动指定规格信息,但值得注意的是,生活中,绘画纸的参数是用于描述纸的,而在这里,参数是用于生成纸的,详情将在后面指出。这里,我们创建了一个信息块,同时为其填写信息,即:宽600px、高400px、RGBA颜色,同时设置使用Alpha通道。

SkImageInfo bitmapInfo = SkImageInfo::Make(600, 400, kRGBA_8888_SkColorType, kPremul_SkAlphaType);

接下来我们需要用这个信息分配空间。

bitmap.allocPixels(bitmapInfo);

接下来就是看起来不能理解但很合理的部分。bitmap作为我们绘制的介质我们却无法直接对其进行绘制,而提供一个SkCanvas供我们绘制。虽然显得有些繁琐,但其实却很合理。bitmap仅作为我们存储的地方。而SkCanvas作为绘制的部分。好比GUI程序界面与其内部数据是分离的,但却不可割舍其中一个。同理,绘制也是如此。SkCanvas并不存储数据,但却提供给我们绘制的方法;而SkBitmap不提供绘制方法,却允许我们将图像数据存储其中。这自然是很合理的。
那如何使用SkCanvas呢?首先,我们知道SkCanvas是不存储数据的,但提供绘制方法,那我们调用方法绘制时数据存何处?自然是SkBitmap,因此,我们需要为SkCanvas绑定一个存储数据的地方——SkBitmap。如下:

SkCanvas canvas(bitmap);

既然SkCanvas为我们提供了绘制的方法,那么,我们想要达成绘制字符串的目的,自然需要调用其中的方法。
这里有两个方法可以使用。
第一种,使用drawSimpleText方法;
第二种,使用drawString方法。
我相信大家也许去尝试使用这两个方法,然而发现这两个方法有许多参数。不急,我们慢慢解析。

第一种方法原型如下:

void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding,
  SkScalar x, SkScalar y, const SkFont &font, 
  SkPaint &paint);

text:待绘制的字符串
byteLength:字符串字节数
encoding:字符串编码
x:起点横坐标
y:起点纵坐标
font:字体
paint:画笔

绘制文本,自然需要我们给出字符串,那如何表示呢?std::string?实际上我们可以使用Skia提供的SkString类存储字符串。这里我们将定义两个字符串,分别用于两种绘制方法。

SkString str_Method1("Drawed by drawSimpleText"),
  str_Method2("Drawed by drawString");

第一个参数是字符串指针,我们只需调用SkStringc_str方法即可。第二个参数我们同样只需调用SkStringsize方法即可。第三个参数,因为我们已经设置代码文件编码为UTF8,因此我们只需设置编码为SkTextEncoding::kUTF8。第四五个参数,我们分别传入绘制起始点的坐标。第六个参数是字体。第七个参数是画笔。

不难发现,这一个方法就带了一堆参数。于是又扯到了字体和画笔上。
接下来,我们将对第六七个参数进行详解。

首先,我们先了解一下字体类——SkFont
顾名思义,这个类自然是对字体的设置。实例化一个对象不必多言,但我们如何初始化呢?
方法如下:

SkFont font(SkTypeface::MakeFromName("Consolas", SkFontStyle::Bold()), 20);

这里我们选择使用Consolas字体,同时设置风格为加粗,大小为20。

接下来就是画笔SkPaint了,其实字面上看,倒不如说是绘画更为贴切,但Skia使用“Paint”这个名字用来储存绘制动作的属性(包括颜色、透明度等),我们即将其叫做更为熟知的“画笔”。

SkPaint paint;
paint.setColor(SkColor(0xFF000000));

万事俱备,只欠东风。现在我们只需要调用drawSimpleText方法即可。

canvas.drawSimpleText(str_Method1.c_str(), str_Method1.size(), SkTextEncoding::kUTF8, 0, 20, font, paint);

至于drawString方法,原型如下:

void drawString(const SkString &str, SkScalar x, SkScalar y, const SkFont& font,
  const SkPaint& paint);

看到原型,相比大家已经知道如何使用了。这里不过多解释。

接下来就是输出为PNG图片了。原理很简单,我们只需声明一个文件输出流,然后使用SkEncodeImage函数编码即可。

SkFILEWStream stream("D:/test.png");
SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);

值得注意的是,第四个参数是一个0-100的整数,用来表示图片质量,100为最大,并且,这个参数只会对jpeg和webp格式生效。


参考代码

#include "pch.h"

int main()
{
	SkBitmap bitmap;
	SkImageInfo bitmapInfo = SkImageInfo::Make(600, 400, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
	bitmap.allocPixels(bitmapInfo);
	SkCanvas canvas(bitmap);
	canvas.clear(0xFFFFFFFF); //注意,这里是ARGB,Alpha通道值在前

	SkString str_Method1("Drawed by drawSimpleText"),
		str_Method2("Drawed by drawString");

	SkFont font(SkTypeface::MakeFromName("Consolas", SkFontStyle::Bold()), 20);
	SkPaint paint;
	paint.setColor(SkColor(0xFF000000)); //同上
	canvas.drawSimpleText(str_Method1.c_str(), str_Method1.size(), SkTextEncoding::kUTF8, 0, 20, font, paint);
	canvas.drawString(str_Method2, 0, 50, font, paint);
	SkFILEWStream stream("D:/test.png");
	SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);

	return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

大海捞针 Skia(C++) 第 3 期:绘制文本 的相关文章

随机推荐

  • java单元测试覆盖率(clover+testng)

    1 testng 介绍 TestNG是一个旨在简化各种测试需求的测试框架 从单元测试 将一个类与其他类分开测试 到集成测试 对由多个类 几个程序包甚至几个外部框架组成的整个系统进行测试 开源免费 基于以maven组件的形式 引入项目 需要修
  • 分享维基百科里的深度学习简介

    简介 编辑 深度学习框架 尤其是基于人工神经网络的框架可以追溯到1980年福岛邦彦提出的新认知机 2 而人工神经网络的历史更为久远 1989年 燕乐存 Yann LeCun 等人开始将1974年提出的标准反向传播算法 3 应用于深度神经网络
  • 【Electron-Vue】构建桌面应用(41)- Electron程序第一次启动时会有短暂的空白页面

    使用Electron开发的时候 会发现安装后第一次启动会出现短暂的空白大概是1 3秒不等 起初是以为在创建窗口的时候会去加载html页面 在加上vue组件的渲染 导致在启动的时候会出现几秒的空白页面 然后渲染之后 就能正常显示 之后的下次启
  • 数据分析整体框架之落地全流程讲解

    小飞象 交流会 人生没有四季 只有两季 努力就是旺季 不努力就是淡季 内部交流 11期 数据分析整体框架 之落地全流程 data analysis 分享人 刘珍珍 数据分析的目的是把隐藏在杂乱无章的数据背后的信息集中和提炼出来 总结出研究对
  • 突破自定义View性能瓶颈

    在Android应用程序中 自定义View是一个非常常见的需求 自定义View可以帮助您创建独特的UI元素 以满足您的应用程序的特定需求 然而 自定义View也可能会导致性能问题 特别是在您的应用程序需要处理大量自定义View的情况下 在本
  • ssm分离增删改查总结

    1后台api 知识点 spring核心 springMVC MyBatis SSM整合实质 service中要访问到mapper 要求mapper代理的对象要交给spring容器 mybatis的事务管理能力弱 事务管理交给spring 搭
  • QT模拟鼠标事件,实现点击双击移动拖拽等

    之前有涉及过一个远程桌面控制的项目 需要传一些指令给远程的电脑 实现简单的桌面点击 移动 拖拉等功能 当时没有时间实现得很好 今天又研究了一下 故此记录 虽然我用的是QT 但核心涉及的还是系统的API 所以其他平台应该也是一样的 废话不多说
  • 决战k8s,Kubernetes、Master节点部署组件,部署kube-proxy、测试、部署Dashboard(Web UI)、超细详解 ,安装篇③完结篇

    文章目录 下面这些操作在master节点完成 创建kubeconfig文件 创建kube proxy kubeconfig文件 下面这些操作在node节点完成 俩个节点上面拉取镜像 systemd管理kubelet组件 部署kube pro
  • 软件测试金融测试岗位,本人亲面

    网上银行转账是怎么测的 设计一下测试用例 回答思路 宏观上可以从质量模型 万能公式 来考虑 重点需要测试转账的功能 性能与安全性 设计测试用例可以使用场景法为主 先列出转账的基本流和备选流 然后设计场景 最后根据场景设计数据 实际面试中需要
  • HLSL 偏导数 ddx / ddy

    HLSL ddx ddy 在光栅化的时刻 GPUs会在同一时刻并行运行很多Fragment Shader 但是并不是一个pixel一个pixel去执行的 而是将其组织在2x2的一组pixels分块中 去并行执行 偏导数就正好是计算的这一块像
  • 如何正确理解JavaScript中的函数和方法

    你真的了解JavaScript的函数和方法吗 你知道它们有什么区别吗 你知道它们是如何定义和调用的吗 你知道它们是如何影响this值的吗 如果你对这些问题感到迷茫 那么本文就是为你准备的 本文将从基础开始 详细解释函数和方法的概念 特点 用
  • 教你实现微信8.0『炸裂』的表情特效

    写在开头 最近微信更新了8 0 其中之一最好玩的莫过于表情包的更新了 大家都在群里纷纷玩起了表情包大战 作为一个前端程序员 这就勾起了我的好奇心 虽然我从来没有实现过这样的动画 但是我还是忍不住想要去实现 最终我花了2天时间去看一些库的源码
  • IDEA 搭建ssm框架 (非maven)

    之前学习的时候大多都是使用maven搭建 但今天想尝试一下不使用maven 但是配置文件都差不多 只不过不使用maven的不用去配置pom xml 而是需要自己导入相应的包 废话不多说 直接开整 1 先看一下我的项目结构 我的项目就只是新建
  • js中parseInt()与parseFloat(),Number(),Boolean(),String()转换

    js将字符串转数值的方法主要有三种 转换函数 强制类型转换 利用js变量弱类型转换 1 转换函数 js提供了parseInt 和parseFloat 两个转换函数 前者把值转换成整数 后者把值转换成浮点数 只有对String类型调用这些方法
  • cesium很全的入门教程-翻译官网和加入自己理解

    Cesium WorkShop cesium快速入门教程 快速入门教程基本涵盖了大多数的CesiumJS API概念 主要用于Cesium基本入门 对Cesium有全面基本的了解和使用 一 概述 本教程会一步一步教会你做一个项目 主要介绍如
  • 为什么 Linux 的 htop 命令完胜 top 命令

    在 Linux 系统中 top 命令用来显示系统中正在运行的进程的实时状态 它显示了一些非常有用的信息 比如 CPU 利用情况 内存消耗情况 以及每个进程情况等 但是 你知道吗 还有另外一个命令行工具 htop 它与传统的 top 命令功能
  • 2023最新计算机大数据毕业设计选题推荐100例

    文章目录 0 前言 1 如何选题 1 1 选题技巧 如何避坑 重中之重 1 2 为什么这么说呢 1 3 难度把控 1 4 题目名称 1 5 最后 2 大数据 选题推荐 2 1 大数据挖掘类 2 2 大数据处理 云计算 区块链 毕设选题 2
  • 使用ESP8266模块在WIFI下通过网页远程控制LED开关

    一 所需器件 1 USB TO TTL 2 LED灯 3 面包板 4 连接线 5 电脑 二 配置Arduino IDE环境 1 安装ESP8266开发板软件包 使用1 6 4及以上版本的Arduino 打开Arduino IDE 打开 文件
  • 关于组件u-input

    关于自定义封装input
  • 大海捞针 Skia(C++) 第 3 期:绘制文本

    前言 本期将正式给大家介绍Skia的使用 文章将涉及一个目的的多种方案多种情况 文章较长 请大家耐心阅读 关键词 PNG图像 文件 文本 字符串 UTF8 UTF16 UTF32 编码转换 Visual Studio 设置 高级保存选项 案