做大型网站建设/雅诗兰黛网络营销策划书
创建SkCanvas
首先,阅读SkCanvasAPI
概述.
Skia
有多个接收SkCanvas
绘图命令的后端.每个后端都有创建SkCanvas
的独特方式.本页给出了每个示例:
光栅化
光栅化
后端将绘画到可由Skia
或客户
管理的内存块
.
推荐用管理画布命令要绘画
内存对象的SkSurface
为Raster
和Ganesh
后端创建
画布.
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
void raster(int width, int height, void (*draw)(SkCanvas*), const char* path) {sk_sp<SkSurface> rasterSurface = SkSurface::MakeRasterN32Premul(width, height);SkCanvas* rasterCanvas = rasterSurface->getCanvas();draw(rasterCanvas);sk_sp<SkImage> img(rasterSurface->makeImageSnapshot());if (!img) { return; }sk_sp<SkData> png = SkPngEncoder::Encode(nullptr, img, {});if (!png) { return; }SkFILEWStream out(path);(void)out.write(png->data(), png->size());
}
或,可显式
指定表面
的内存,而不是让Skia
管理它.
#include <vector>
#include "include/core/SkSurface.h"
std::vector<char> raster_direct(int width, int height, void (*draw)(SkCanvas*)) {SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);size_t rowBytes = info.minRowBytes();size_t size = info.getSafeSize(rowBytes);std::vector<char> pixelMemory(size); // 分配内存sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect( info, &pixelMemory[0], rowBytes);SkCanvas* canvas = surface->getCanvas();draw(canvas);return pixelMemory;
}
GPU
GPU
表面必须有管理GPU
环境及纹理和字体
相关缓存的GrContext
对象.GrContexts
与OpenGL
环境或Vulkan
设备一一匹配
.
也即,使用相同的OpenGL
环境或Vulkan
设备渲染到的所有SkSurfaces
都应共享一个GrContext
.Skia
不会为你创建OpenGL
环境或Vulkan
设备.
在OpenGL
模式下,还假定在调用Skia
时,已为当前线程的当前环境
设置了正确的OpenGL
环境.
#include "include/gpu/GrDirectContext.h"#include "include/gpu/gl/GrGLInterface.h"#include "include/gpu/ganesh/gl/GrGLInterface.h"#include "include/core/SkData.h"#include "include/core/SkImage.h"#include "include/core/SkStream.h"#include "include/core/SkSurface.h"void gl_example(int width, int height, void (*draw)(SkCanvas*), const char* path) {// 已经创建了`OpenGL`上下文并绑定了它sk_sp<const GrGLInterface> interface = nullptr;//将`interface`保留为`null`会使`Skia`按特定平台方式,提取当前上下文的`OpenGL`函数的指针.或,可创建自己的`GrGLInterface`,并初化它,以附加到备用`OpenGL`实现或拦截`Skia`的`OpenGL`调用sk_sp<GrDirectContext> context = GrDirectContexts::MakeGL(interface);SkImageInfo info = SkImageInfo:: MakeN32Premul(width, height);sk_sp<SkSurface> gpuSurface(SkSurface::MakeRenderTarget(context.get(), skgpu::Budgeted::kNo, info));if (!gpuSurface) {SkDebugf("SkSurface::MakeRenderTarget returned null\n");return;}SkCanvas* gpuCanvas = gpuSurface->getCanvas();draw(gpuCanvas);sk_sp<SkImage> img(gpuSurface->makeImageSnapshot());if (!img) { return; }// 必须传递非空上下文,以便可以读回和编码`像素`sk_sp<SkData> png = SkPngEncoder::Encode(context.get(), img, {});if (!png) { return; }SkFILEWStream out(path);(void)out.write(png->data(), png->size());}
SKPDF
格式
因为文档
必须包含多页,SkPDF
后端使用SkDocument
而不是SkSurface
.
#include "include/docs/SkPDFDocument.h"#include "include/core/SkStream.h"void skpdf(int width, int height, void (*draw)(SkCanvas*), const char* path) {SkFILEWStream pdfStream(path);auto pdfDoc = SkPDF::MakeDocument(&pdfStream);SkCanvas* pdfCanvas = pdfDoc->beginPage(SkIntToScalar(width), SkIntToScalar(height));draw(pdfCanvas);pdfDoc->close();}
SkPicture
SkPicture
后端使用SkPictureRecorder
而不是SkSurface
.
#include "include/core/SkPictureRecorder.h"#include "include/core/SkPicture.h"#include "include/core/SkStream.h"void picture(int width, int height, void (*draw)(SkCanvas*), const char* path) {SkPictureRecorder recorder;SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width), SkIntToScalar(height));draw(recordingCanvas);sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();SkFILEWStream skpStream(path);// 用`viewer --skps PATH_TO_SKP --slide SKP_FILE`,打开SKP文件picture->serialize(&skpStream);}
空画布
空画布是忽略
所有绘图命令
且无操作
的画布.
#include "include/utils/SkNullCanvas.h"void null_canvas_example(int, int, void (*draw)(SkCanvas*), const char*) {std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();draw(nullCanvas.get()); // 闲着}
SkXPS
(仍在实验阶段)把SkXPS
画布写入XPS
文档.
#include "include/core/SkDocument.h"#include "include/core/SkStream.h"#ifdef SK_BUILD_FOR_WINvoid skxps(IXpsOMObjectFactory* factory; int width, int height, void (*draw)(SkCanvas*), const char* path) {SkFILEWStream xpsStream(path);sk_sp<SkDocument> xpsDoc = SkDocument::MakeXPS(&pdfStream, factory);SkCanvas* xpsCanvas = xpsDoc->beginPage(SkIntToScalar(width), SkIntToScalar(height));draw(xpsCanvas);xpsDoc->close();}#endif
SkSVG
(仍在实验阶段)把SkSVG
画布写入SVG
文档.
#include "include/core/SkStream.h"#include "include/svg/SkSVGCanvas.h"#include "SkXMLWriter.h"void sksvg(int width, int height, void (*draw)(SkCanvas*), const char* path) {SkFILEWStream svgStream(path);std::unique_ptr<SkXMLWriter> xmlWriter( new SkXMLStreamWriter(&svgStream));SkRect bounds = SkRect::MakeIWH(width, height);std::unique_ptr<SkCanvas> svgCanvas = SkSVGCanvas::Make(bounds, xmlWriter.get());draw(svgCanvas.get());}
例
要试用此代码,请使用新的单元测试
,并把这些函数包装
在一起:
#include "include/core/SkCanvas.h"#include "include/core/SkPath.h"#include "tests/Test.h"void example(SkCanvas* canvas) {const SkScalar scale = 256.0f;const SkScalar R = 0.45f * scale;const SkScalar TAU = 6.2831853f;SkPath path;for (int i = 0; i < 5; ++i) {SkScalar theta = 2 * i * TAU / 5;if (i == 0) {path.moveTo(R * cos(theta), R * sin(theta));} else {path.lineTo(R * cos(theta), R * sin(theta));}}path.close();SkPaint p;p.setAntiAlias(true);canvas->clear(SK_ColorWHITE);canvas->translate(0.5f * scale, 0.5f * scale);canvas->drawPath(path, p);}DEF_TEST(FourBackends, r) {raster( 256, 256, example, "out_raster.png" );gl_example( 256, 256, example, "out_gpu.png" );skpdf( 256, 256, example, "out_skpdf.pdf" );picture( 256, 256, example, "out_picture.skp");}
画布概述
绘图环境
细节
SkCanvas
是Skia
的绘图环境
.它知道直接在哪绘图
(即屏幕外像素
的屏幕
位置),并维护一堆矩阵和剪切
.
但注意,与其他API
(如postscript,cairo
或awt
)中的类似环境不同,Skia
不会在环境
中存储其他(如颜色,笔大小
)绘图属性
.相反,在每次
绘画调用中,通过SkPaint
显式指定它们.
确切地说,画笔
而不是画布
,描述绘画
的颜色和风格
.
首先,可能想要擦除
整个画布.可绘画巨大
矩形来完成,但有更简单
方法.
void draw(SkCanvas* canvas) {SkPaint paint;paint.setColor(SK_ColorWHITE);canvas->drawPaint(paint);}
这(当然,尊重当前剪切)指定
绘画用的颜色或着色器
(和xfermode
),并填充整个画布
.如果画笔
中有个着色器
,则它也会遵循画布
上的当前矩阵
(见SkShader
).
如果(用可选的xfermode
)只想绘画
个颜色,你可直接调用drawColor()
,这样就不必赋值
画笔了.
void draw(SkCanvas* canvas) {canvas->drawColor(SK_ColorWHITE);}
所有其他绘画API
类似,都以画笔
参数结尾.
在某些
调用中,传递画笔
的指针,而不是引用
.这时,paint
参数可能为null
.其他时候,必需要有paint
参数.
画笔概览
每当你在Skia
中画笔
某些内容时,想要指定颜色
,或如何与背景
混合,或使用的风格或字体
,都可在画笔
中指定这些属性.
与SkCanvas
不同,画笔
不维护内部状态栈
(即画笔上不保存/恢复
).然而,画笔
是轻量
的,因此客户可创建和维护
多个用途不同的画笔
对象.
从画布
状态中,分解出所有这些颜色和风格
属性,并转换为(多个
)画笔
对象中,因为只需维护矩阵
和剪切
设置栈,可更加高效的保存/恢复画布
.
可显示三个不同
画笔,每种画笔
都按以不同的风格设置.现在,调用者
可自由地混合
这些画笔
,可原样使用它们,也可在绘图
过程中修改它们.
除了颜色,描边和文本值
等简单属性外,画笔还支持特效
.它是绘图管线
不同方面的子类
,引用画笔
时(每个子类
都按引用计数
),调用它以覆盖
绘图管线的某些部分
.
如,要用渐变
而不是单色
画笔,请为画笔
指定SkShader
.
现在,使用该画笔的内容都使用调用MakeLinear()
中指定的渐变画笔
.返回的着色器
对象是引用计数
的.每当赋值着色
器等特效对象
给画笔
时,画笔都会增加引用计数
.
为了平衡,上面赋值给画笔后,在着色器
上马上调用unref()
.现在,画笔
是该着色器的唯一"物主"
,当画笔
出域或为其赋值另一个着色器(或null
)时,它自动在着色器
上调用unref()
.
有6种类型的特效可赋值
给画笔:
1,SkPathEffect
,在生成α
掩码(如破折号)修改几何路径
2,SkRasterizer
,合成
自定义掩码图层(如阴影
)
3,SkMaskFilter
,在着色及绘画前修改α
掩码(如模糊)
4,SkShader
:如渐变
(线性,径向,扫描
),位图模式(夹,重复,镜像
)
5,SkColorFilter
,在混合
前修改源颜色
(如颜色矩阵
)
6,SkBlendMode
:如porter-duff
传输模式,混合模式等
画笔
还有SkTypeface
的引用.字体
表示来测量和绘画
文本的特定字体风格
.画笔不仅可绘画
文本,还可测量
文本.
paint.measureText(...);paint.getTextBounds(...);paint.textToGlyphs(...);paint.getFontMetrics(...);
SkBlend
模式
以下示例演示了Skia
的所有标准混合模式
.此例中,源
是有水平α
渐变的纯洋红色
,目标为有垂直α
渐变的纯青色
.
SkShader
定义了几个着色器(除了已提到的线性渐变):
1,位图
着色器
2,径向渐变
着色器
3,两点锥形
渐变着色器
4,扫描
渐变着色器
5,分形
噪声着色器
6,湍流
噪声着色器
7,合成
着色器
SkMask
过滤器
1,模糊
掩码过滤器
SkColor
过滤器
ColorMatrix
颜色过滤器
颜色表
颜色过滤器
SkPathEffect
1,SkPath2DPathEffect
:用矩阵
定义晶格,标记指定路径
以填充
形状.
2,SkLine2DPathEffect
:路径是要描边
而不是要填充
的直线路径的SkPath2DPathEffect
的特例.
3,SkPath1DPathEffect
:通过复制指定路径
沿着画笔
路径,创建
类似破折号
的特效.
4,SkCornerPathEffect
:一个可变形尖角
的特效(如圆角).
5,SkDashPathEffect
:实现破折号
的路径特效.
6,SkDiscretePathEffect
:此路径特效把路径切成离散段
,并随机替换它们.
7,SkComposePathEffect
:先应用内部pathEffect
,再外部pathEffect
(即outer(inner(path))
)的pathEffect
特效.
8,SkSumPathEffect
:按如下应用两个特效的pathEffect
特效:
sequence (first(path) + second(path)).
相关文章:

2312skia,16画布
创建SkCanvas 首先,阅读SkCanvasAPI概述. Skia有多个接收SkCanvas绘图命令的后端.每个后端都有创建SkCanvas的独特方式.本页给出了每个示例: 光栅化 光栅化后端将绘画到可由Skia或客户管理的内存块. 推荐用管理画布命令要绘画内存对象的SkSurface为Raster和Ganesh后端创建画…...

mysql文本类型的最大长度限制
mysql支持很多类型,不同的文本有不同的长度限制。可以根据实际需要进行选择。 TINYBLOB, TINYTEXT L 1 bytes, where L < 2^8 (255 Bytes) BLOB, TEXT L 2 bytes, where L < 2^16 (64 Kilobytes) MEDIUMBLOB, MEDIUMTEXT L 3 b…...

ASP.NET《数据库原理及应用技术》课程指导平台的开发
1.1 系统设计目标 研制《数据库原理及应用技术》课程指导平台在功能上可以满足网络课堂教学活动的需要,在Internet上实现教学活动的各个环节。系统的基本设计原则有:先进性与方便性原则、功能实用性原则、开放性与可扩展性原则等。系统设计时采用较好的…...

OSHI-操作系统和硬件信息库
文章目录 引言一、快速入门1.1 OSHI的简介1.2 引入依赖1.3 涉及的包(package)1.4 涉及的核心类 二、操作系统信息:OperatingSystem2.1 总揽2.2 文件系统信息:FileSystem2.3 网络参数信息:NetworkParams2.4 进程信息&am…...

基于Java SSM框架+Vue实现企业公寓后勤管理系统项目【项目源码+论文说明】计算机毕业设计
基于java的SSM框架Vue实现企业宿舍后勤管理网站演示 摘要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所…...

stm32mp157和imx6ull在设备树节点上设置ap3216c的主要区别
stm32mp157和imx6ull在设备树节点上设置ap3216c的主要区别是,它们使用的不同的硬件架构和不同的设备树格式。以下是两者之间的差异: 硬件架构:stm32mp157是基于ARM Cortex-M4内核的微控制器,而imx6ull则是基于ARM Cortex-A7内核的…...

网工学习6-配置和管理 VLAN
6.1VLAN概念 1> 什么是 VLAN? VLAN 是一种在交换机上划分逻辑网段的二层技术。 2> 为什么要通过交换机划分网段? ① 因为交换机的端口密度比路由器高,并且价格比路由器低,所以组网成本更低。 ② 因为交换机划分网段比…...

MySQL库与表的备份
库的备份 备份 语法 mysqldump -P3306 -u root -p 密码 -B 数据库名 > 数据库备份存储的文件路径 例 mysqldump -P3306 -u root -p123456 -B mytest > D:/mytest.sql 注意 这是在linux命令行下。 还原 语法 scource 数据库文件路径 例 source D:/mysql-5.7.22/mytest.s…...

Python核心编程之基础内功
目录 一、语句和语法 1、 注释( # ) 2、继续( \ ) 3、多个语句构成代码组(:):...

GPT4-Turbo技术原理研发现状及未来应用潜力分析报告
今天分享的是GPT4-Turb系列深度研究报告:《GPT4-Turbo技术原理研发现状及未来应用潜力分析报告》。 (报告出品方:深度行业分析研究) 报告共计:46页 图像理解能力提升:三大视觉学习方法 为打造视觉大模…...

为什么 SQL 不适合图数据库
背景 “为什么你们的图形产品不支持 SQL 或类似 SQL 的查询语言?” 过去,我们的一些客户经常问这个问题,但随着时间的推移,这个问题变得越来越少。 尽管一度被忽视,但图数据库拥有无缝设计并适应其底层数据结构的查询…...

【Rust日报】2023-12-02 深度学习框架 Burn 发布 v0.11.0
深度学习框架 Burn 发布 v0.11.0 深度学习框架 Burn 发布 v0.11.0,新版本引入了自动内核融合(Kernel Fusion)功能,大大提升了访存密集型(memory-bound)操作的性能。同时宣布成立 Tracel AI (https://tracel…...

MySQL性能调优-1-实际优化案例
关于SQL优化的思路,一般都是使用执行计划看看是否用到了索引,主要可能有两大类情况: 对业务字段建立了二级联合索引,但是MySQL错误地觉得走主键聚族索引全表扫描效率更高,而没有走二级索引 走二级索引,但…...

JavaScript空值合并运算符
The Nullish Coalescing Operator(空值合并运算符)是一种 JavaScript 的新运算符,用于解决默认值设定中存在的一些问题。它的语法为 ??(两个问号),表示当左侧的操作数为 null 或 undefined 时,…...

Spring Boot 集成 spring security 01
一、导入依赖(pom.xml) <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&qu…...

C 编程中使用字符串
理解字符串: C 中的字符串是使用字符数组来操作的。数组中的每个字符对应字符串的一个元素,字符串的结尾由空字符(\0)标记。这个空字符至关重要,因为它表示字符串的结尾,并允许函数确定字符串在内存中的结…...

【GD32307E-START】04 使用TinyMaix进行手写数字识别
【GD32307E-START】04 使用TinyMaix进行手写数字识别 参考博客 【GD32F427开发板试用】使用TinyMaix进行手写数字识别 https://blog.csdn.net/weixin_47569031/article/details/129009839 软硬件平台 GD32F307E-START Board开发板GCC Makefile TinyMaix简介 TinyMaix是国…...

qt-C++笔记之识别点击鼠标右键、点击位置以及Qt坐标系详解
qt-C笔记之识别点击鼠标右键、点击位置以及Qt坐标系详解 code review! 文章目录 qt-C笔记之识别点击鼠标右键、点击位置以及Qt坐标系详解1.示例运行2.event->pos();详解3.event->pos()的坐标系原点4.Qt中的坐标系详解5.QMainWindow::mousePressEvent(event);详解 1.示例…...

小程序开发平台源码系统:搭建新的商业体系 附带完整的搭建教程
小程序开发平台源码系统是在移动互联网快速发展的背景下诞生的。随着微信小程序的普及,越来越多的人开始关注小程序的开发与运营。然而,对于很多初学者和小型企业来说,开发一个小程序需要专业的技术知识和大量的时间投入,这无疑是…...

css3新增的伪类有哪些?
CSS3新增的伪类有: :first-of-type,选择属于其父元素的特定类型的第一个子元素。:last-of-type,选择属于其父元素的特定类型的最后一个子元素。:only-of-type,选择属于其父元素的特定类型的唯一子元素。:only-child,选…...

开源软件license介绍与检测
开源License介绍 通俗来讲,开源许可证就是一种允许软件使用者在一定条件内按照需要自由使用和修改软件及其源代码的的法律条款。借此条款,软件作者可以将这些权利许可给使用者,并告知使用限制。这些许可条款可以由个人、商业公司或非赢利组织…...

【LeeCode】142.环形链表II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数…...

nodejs微信小程序+python+PHP健身房信息管理系统的设计与实现-计算机毕业设计推荐
目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性:…...

springboot集成springsecurity
转载自:www.javaman.cn 1、整合springsecurity 添加pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId> </dependency>2、springsecurity认证授权流程…...

脏读、不可重复读、幻读
一、脏读 A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏…...

思维模型 反馈效应
本系列文章 主要是 分享 思维模型,涉及各个领域,重在提升认知。反馈促进改进。 1 反馈效应的应用 1.1 反馈效应在营销中的应用 1 “可口可乐与百事可乐之战” 在 20 世纪 80 年代,可口可乐公司是全球最大的饮料公司之一,其市场…...

【PyTorch】线性回归
文章目录 1. 模型与代码实现2. Q&A 1. 模型与代码实现 模型 y ^ w 1 x 1 . . . w d x d b w ⊤ x b . \hat{y} w_1 x_1 ... w_d x_d b \mathbf{w}^\top \mathbf{x} b. y^w1x1...wdxdbw⊤xb. 代码实现 import torch from torch import nn from to…...

硝烟弥漫的科技战场——GPT之战
没想到2023年的双11之后,还能看到如此多的科技圈大佬针对GPT提出火药味十足的讨论和极具戏剧性的表演。 历史回顾: 11月6日,OpenAI发布会:GPT-4 Turbo模型、GPT应用商店、开源Whisper-large-v3等;11月17日࿰…...

re:Invent 构建未来:云计算生成式 AI 诞生科技新局面
文章目录 前言什么是云计算云计算类型亚马逊云科技云计算最多的功能最大的客户和合作伙伴社区最安全最快的创新速度最成熟的运营专业能力 什么是生成式 AI如何使用生成式 AI后记 前言 在科技发展的滚滚浪潮中,我们见证了云计算的崛起和生成式 AI 的突破,…...

oneApi实现并⾏排序算法
零、OneApi简介 oneAPI是由英特尔推出的一个开放、统一的编程模型和工具集合,旨在简化跨不同硬件架构的并行计算。oneAPI的目标是提供一个统一的编程模型,使开发人员能够使用相同的代码在不同类型的硬件上进行并行计算,包括CPU、GPU、FPGA和…...