1# 复杂绘制效果(C/C++) 2 3<!--Kit: ArkGraphics 2D--> 4<!--Subsystem: Graphics--> 5<!--Owner: @hangmengxin--> 6<!--Designer: @wangyanglan--> 7<!--Tester: @nobuggers--> 8<!--Adviser: @ge-yafang--> 9 10除了基础填充颜色、描边颜色和一些样式设置的绘制效果外,还支持通过画刷和画笔实现更多复杂的绘制效果。比如: 11 12 13- 混合模式。 14 15- 路径效果,如虚线效果。 16 17- 着色器效果,如线性渐变、径向渐变等。 18 19- 滤波效果,如模糊效果等。 20 21 22## 混合模式 23 24混合模式可以用于画笔或画刷,它定义了如何将源像素(要绘制的内容)与目标像素(已存在于画布上的内容)进行组合。 25 26可以使用OH_Drawing_BrushSetBlendMode()接口将混合模式应用于画刷中,使用OH_Drawing_PenSetBlendMode()接口将混合模式应用于画笔中。这两个接口都需要接受一个参数OH_Drawing_BlendMode,即混合模式的类型,具体可参考[OH_Drawing_BlendMode](../reference/apis-arkgraphics2d/capi-drawing-types-h.md#oh_drawing_blendmode)。 27 28此处以使用画刷设置叠加混合模式为例(为了防止混合模式的效果被背景色干扰,示例中的canvas并未设置背景色,使用的是默认的黑色背景),关键示例和效果示意图如下所示: 29 30```c++ 31// 创建画刷对象 32OH_Drawing_Brush* brush = OH_Drawing_BrushCreate(); 33// 设置目标像素颜色 34OH_Drawing_BrushSetColor(brush, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0x00, 0x00)); 35// 将目标像素的画刷效果设置到Canvas中 36OH_Drawing_CanvasAttachBrush(canvas, brush); 37// 创建矩形对象 38OH_Drawing_Rect *rect = OH_Drawing_RectCreate(100, 100, 600, 600); 39// 绘制矩形(目标像素) 40OH_Drawing_CanvasDrawRect(canvas, rect); 41// 设置源像素颜色 42OH_Drawing_BrushSetColor(brush, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0xFF)); 43// 设置混合模式为叠加模式 44OH_Drawing_BrushSetBlendMode(brush, OH_Drawing_BlendMode::BLEND_MODE_PLUS); 45// 将源像素的画刷效果设置到Canvas中 46OH_Drawing_CanvasAttachBrush(canvas, brush); 47// 创建圆心的点对象 48OH_Drawing_Point *point = OH_Drawing_PointCreate(600, 600); 49// 绘制圆(源像素) 50OH_Drawing_CanvasDrawCircle(canvas, point, 300); 51// 去除掉画布中的画刷 52OH_Drawing_CanvasDetachBrush(canvas); 53// 销毁各类对象 54OH_Drawing_RectDestroy(rect); 55OH_Drawing_BrushDestroy(brush); 56OH_Drawing_PointDestroy(point); 57``` 58 59 60 61 62## 路径效果 63 64路径效果如虚线效果,只用于画笔。 65 66可使用OH_Drawing_CreateDashPathEffect()接口设置路径效果。接口接受3个参数,分别为: 67 68- 浮点数数组intervals:表示虚线或者点线的间隔。 69 70- 整数count:表示intervals数组中的元素数量。 71 72- 浮点数phase:表示在intervals数组中的偏移量,即从数组的哪个位置开始应用虚线或点线效果。 73 74此处以绘制矩形虚线路径效果为例,关键示例和效果示意图如下所示: 75 76```c++ 77// 创建画笔 78OH_Drawing_Pen *pen = OH_Drawing_PenCreate(); 79// 设置画笔描边颜色 80OH_Drawing_PenSetColor(pen, 0xffff0000); 81// 设置画笔线宽 82OH_Drawing_PenSetWidth(pen, 10); 83// 表示10px的实线,5px的间隔,2px的实线,5px的间隔,以此循环 84float intervals[] = {10, 5, 2, 5}; 85// 设置虚线路径效果 86OH_Drawing_PathEffect *pathEffect = OH_Drawing_CreateDashPathEffect(intervals, 4, 0.0); 87OH_Drawing_PenSetPathEffect(pen, pathEffect); 88// 在画布上设置画笔,请确保已获取得到画布对象 89OH_Drawing_CanvasAttachPen(canvas, pen); 90// 创建矩形 91OH_Drawing_Rect *rect = OH_Drawing_RectCreate(300, 300, 900, 900); 92// 绘制矩形 93OH_Drawing_CanvasDrawRect(canvas, rect); 94// 去除掉画布中的画笔 95OH_Drawing_CanvasDetachPen(canvas); 96// 销毁各类对象 97OH_Drawing_PenDestroy(pen); 98OH_Drawing_RectDestroy(rect); 99OH_Drawing_PathEffectDestroy(pathEffect); 100``` 101 102| 不设置虚线路径效果的示意图 | 设置虚线效果的示意图 | 103| -------- | -------- | 104|  |  | 105 106 107## 着色器效果 108 109着色器效果基于画刷或画笔实现,可使用OH_Drawing_BrushSetShaderEffect()接口设置画刷的着色器效果,或者使用 OH_Drawing_PenSetShaderEffect()接口设置画笔的着色器效果。当前支持不同的着色器效果,如线性渐变着色器效果、径向渐变着色器效果、扇形渐变着色器效果。 110 111着色器相关接口和具体参数的说明请见[drawing_shader_effect](../reference/apis-arkgraphics2d/capi-drawing-shader-effect-h.md)。 112 113 114### 线性渐变着色器效果 115 116可使用OH_Drawing_ShaderEffectCreateLinearGradient()接口创建想要设置的线性渐变着色器效果。接口接受6个参数,分别为开始点、结束点、颜色数组、相对位置数组、颜色数组的大小以及平铺模式。 117 118- 开始点和结束点用来确定渐变方向。 119 120- 颜色数组用于存储渐变使用到的颜色。 121 122- 相对位置数组则用于确定每种颜色在渐变中的相对位置,如果相对位置为空,颜色将会被均匀地分布在开始点和结束点之间。 123 124- 平铺模式用于确定如何在渐变区域之外继续渐变效果,平铺模式分为以下4类: 125 - CLAMP:当图像超出其原始边界时,复制边缘颜色。 126 - REPEAT:在水平和垂直方向上重复图像。 127 - MIRROR:在水平和垂直方向上重复图像,并在相邻的图像之间交替使用镜像图像。 128 - DECAL:只在原始域内绘制,在其他地方返回透明黑色。 129 130此处以绘制矩形并使用画刷设置线性渐变着色器效果为例,关键示例和效果示意图如下所示: 131 132```c++ 133// 开始点 134OH_Drawing_Point *startPt = OH_Drawing_PointCreate(20, 20); 135// 结束点 136OH_Drawing_Point *endPt = OH_Drawing_PointCreate(900, 900); 137// 颜色数组 138uint32_t colors[] = {0xFFFFFF00, 0xFFFF0000, 0xFF0000FF}; 139// 相对位置数组 140float pos[] = {0.0f, 0.5f, 1.0f}; 141// 创建线性渐变着色器效果 142OH_Drawing_ShaderEffect *colorShaderEffect = 143 OH_Drawing_ShaderEffectCreateLinearGradient(startPt, endPt, colors, pos, 3, OH_Drawing_TileMode::CLAMP); 144// 创建画刷对象 145OH_Drawing_Brush* brush = OH_Drawing_BrushCreate(); 146// 基于画刷设置着色器效果 147OH_Drawing_BrushSetShaderEffect(brush, colorShaderEffect); 148// 在画布上设置画刷,请确保已获取得到画布对象 149OH_Drawing_CanvasAttachBrush(canvas, brush); 150OH_Drawing_Rect *rect = OH_Drawing_RectCreate(100, 100, 900, 900); 151 // 绘制矩形 152OH_Drawing_CanvasDrawRect(canvas, rect); 153// 去除掉画布中的画刷 154OH_Drawing_CanvasDetachBrush(canvas); 155// 销毁各类对象 156OH_Drawing_BrushDestroy(brush); 157OH_Drawing_RectDestroy(rect); 158OH_Drawing_ShaderEffectDestroy(colorShaderEffect); 159OH_Drawing_PointDestroy(startPt); 160OH_Drawing_PointDestroy(endPt); 161``` 162 163此例绘制的具有线性渐变着色器效果的矩形如下所示: 164 165 166 167 168### 径向渐变着色器效果 169 170可使用OH_Drawing_ShaderEffectCreateRadialGradient()接口创建想要设置的径向渐变着色器效果。接口接受6个参数,分别为圆心坐标(centerPt)、半径(radius)、颜色数组(colors)、相对位置数组(pos)、颜色和位置的数量(size)以及平铺模式(OH_Drawing_TileMode)。 171 172其实现方式与线性渐变着色器类似,不同的是,径向渐变是由圆心开始向外径向渐变的。 173 174此处以绘制矩形并使用画刷设置径向渐变着色器效果为例,关键示例和效果示意图如下所示: 175 176```c++ 177// 圆心坐标 178OH_Drawing_Point *centerPt = OH_Drawing_PointCreate(500, 500); 179// 半径 180float radius = 600; 181// 颜色数组 182uint32_t gColors[] = {0xFFFF0000, 0xFF00FF00, 0xFF0000FF}; 183// 相对位置数组 184float gPos[] = {0.0f, 0.25f, 0.75f}; 185// 创建径向渐变着色器效果 186OH_Drawing_ShaderEffect *colorShaderEffect = 187 OH_Drawing_ShaderEffectCreateRadialGradient(centerPt, radius, gColors, gPos, 3, OH_Drawing_TileMode::REPEAT); 188// 创建画刷对象 189OH_Drawing_Brush* brush = OH_Drawing_BrushCreate(); 190// 基于画刷设置着色器效果 191OH_Drawing_BrushSetShaderEffect(brush, colorShaderEffect); 192// 在画布上设置画刷,请确保已获取得到画布对象 193OH_Drawing_CanvasAttachBrush(canvas, brush); 194OH_Drawing_Rect *rect = OH_Drawing_RectCreate(100, 100, 900, 900); 195 // 绘制矩形 196OH_Drawing_CanvasDrawRect(canvas, rect); 197// 去除掉画布中的画刷 198OH_Drawing_CanvasDetachBrush(canvas); 199// 销毁各类对象 200OH_Drawing_BrushDestroy(brush); 201OH_Drawing_RectDestroy(rect); 202OH_Drawing_ShaderEffectDestroy(colorShaderEffect); 203OH_Drawing_PointDestroy(centerPt); 204``` 205 206此例绘制的具有径向渐变着色器效果的矩形如下所示: 207 208 209 210 211### 扇形渐变着色器效果 212 213可使用OH_Drawing_ShaderEffectCreateSweepGradient()接口创建想要设置的扇形渐变着色器效果。接口接受5个参数,分别是中心点、颜色数组、相对位置数组、颜色和相对位置的数量以及平铺模式。 214 215其实现方式也与线性渐变着色器类似,不同的是,扇形渐变是在围绕中心点旋转的过程中渐变。 216 217此处以绘制矩形并使用画刷设置扇形渐变着色器效果为例,关键示例和效果示意图如下所示: 218 219```c++ 220// 中心点 221OH_Drawing_Point *centerPt = OH_Drawing_PointCreate(500, 500); 222// 颜色数组 223uint32_t colors[3] = {0xFF00FFFF, 0xFFFF00FF, 0xFFFFFF00}; 224// 相对位置数组 225float pos[3] = {0.0f, 0.5f, 1.0f}; 226// 创建扇形渐变着色器效果 227OH_Drawing_ShaderEffect* colorShaderEffect = 228 OH_Drawing_ShaderEffectCreateSweepGradient(centerPt, colors, pos, 3, OH_Drawing_TileMode::CLAMP); 229// 创建画刷对象 230OH_Drawing_Brush* brush = OH_Drawing_BrushCreate(); 231// 基于画刷设置着色器效果 232OH_Drawing_BrushSetShaderEffect(brush, colorShaderEffect); 233// 在画布上设置画刷,请确保已获取得到画布对象 234OH_Drawing_CanvasAttachBrush(canvas, brush); 235OH_Drawing_Rect *rect = OH_Drawing_RectCreate(100, 100, 900, 900); 236 // 绘制矩形 237OH_Drawing_CanvasDrawRect(canvas, rect); 238// 去除掉画布中的画刷 239OH_Drawing_CanvasDetachBrush(canvas); 240// 销毁各类对象 241OH_Drawing_BrushDestroy(brush); 242OH_Drawing_RectDestroy(rect); 243OH_Drawing_ShaderEffectDestroy(colorShaderEffect); 244OH_Drawing_PointDestroy(centerPt); 245``` 246 247此例绘制的具有扇形渐变着色器效果的矩形如下所示: 248 249 250 251 252## 滤波器效果 253 254滤波器效果可基于画刷或画笔实现。可使用OH_Drawing_PenSetFilter()接口设置画笔的滤波器效果,或者使用OH_Drawing_BrushSetFilter()接口设置画刷的滤波器效果。当前支持不同的滤波器效果,比如图像滤波器、颜色滤波器、蒙版滤波器。 255 256滤波器相关接口和具体参数的说明请见[drawing_filter.h](../reference/apis-arkgraphics2d/capi-drawing-filter-h.md)。 257 258 259### 颜色滤波器效果 260 261颜色滤波器可基于画笔或画刷实现,颜色滤波器的相关接口和具体参数的说明请见[drawing_color_filter.h](../reference/apis-arkgraphics2d/capi-drawing-color-filter-h.md)。 262 263目前可实现多种颜色滤波器,包括如下: 264 265- 具有混合模式的颜色滤波器。 266 267- 具有5x4颜色矩阵的颜色滤波器。 268 269- 将SRGB的伽玛曲线应用到RGB颜色通道的颜色滤波器。 270 271- 将RGB颜色通道应用于SRGB的伽玛曲线的颜色滤波器。 272 273- 将其输入的亮度值乘以透明度通道, 并将红色、绿色和蓝色通道设置为零的颜色滤波器。 274 275- 由两个颜色滤波器组合而成的颜色滤波器。 276 277此处以具有5x4颜色矩阵的颜色滤波器为例。 278 279可使用OH_Drawing_ColorFilterCreateMatrix()接口创建具有5x4颜色矩阵的颜色滤波器。接口接受1个参数,表示为颜色矩阵,它是一个长度为20的浮点数数组。数组格式如下: 280 281[ a0, a1, a2, a3, a4 ] 282 283[ b0, b1, b2, b3, b4 ] 284 285[ c0, c1, c2, c3, c4 ] 286 287[ d0, d1, d2, d3, d4 ] 288 289对于每个原始的像素颜色色值(R, G, B, A),变换后的色值(R', G', B', A')计算公式为: 290 291R' = a0\*R + a1\*G + a2\*B + a3\*A + a4 292 293G' = b0\*R + b1\*G + b2\*B + b3\*A + b4 294 295B' = c0\*R + c1\*G + c2\*B + c3\*A + c4 296 297A' = d0\*R + d1\*G + d2\*B + d3\*A + d4 298 299此处以绘制矩形并使用画刷设置具有5x4颜色矩阵的颜色滤波器效果为例,关键示例和效果示意图如下所示: 300 301```c++ 302// 创建画刷 303OH_Drawing_Brush *brush = OH_Drawing_BrushCreate(); 304// 设置画刷抗锯齿 305OH_Drawing_BrushSetAntiAlias(brush, true); 306// 设置画刷填充颜色 307OH_Drawing_BrushSetColor(brush, 0xffff0000); 308// 设置颜色矩阵 309const float matrix[20] = { 310 1, 0, 0, 0, 0, 311 0, 1, 0, 0, 0, 312 0, 0, 0.5f, 0.5f, 0, 313 0, 0, 0.5f, 0.5f, 0 314}; 315 316// 创建滤波器颜色 317OH_Drawing_ColorFilter* colorFilter = OH_Drawing_ColorFilterCreateMatrix(matrix); 318// 创建一个滤波器对象 319OH_Drawing_Filter *filter = OH_Drawing_FilterCreate(); 320// 为滤波器对象设置颜色滤波器 321OH_Drawing_FilterSetColorFilter(filter, colorFilter); 322// 设置画刷的滤波器效果 323OH_Drawing_BrushSetFilter(brush, filter); 324// 在画布上设置画刷,请确保已获取得到画布对象 325OH_Drawing_CanvasAttachBrush(canvas, brush); 326// 创建矩形 327OH_Drawing_Rect *rect = OH_Drawing_RectCreate(300, 300, 900, 900); 328// 绘制矩形 329OH_Drawing_CanvasDrawRect(canvas, rect); 330// 去除掉画布中的画刷 331OH_Drawing_CanvasDetachBrush(canvas); 332// 销毁各类对象 333OH_Drawing_BrushDestroy(brush); 334OH_Drawing_ColorFilterDestroy(colorFilter); 335OH_Drawing_RectDestroy(rect); 336OH_Drawing_FilterDestroy(filter); 337``` 338 339| 不设置颜色滤波器效果的示意图 | 设置5x4颜色矩阵的颜色滤波器效果的示意图 | 340| -------- | -------- | 341|  |  | 342 343 344### 图像滤波器效果 345 346图像滤波器可基于画笔或画刷来实现,图像滤波器的相关接口和具体参数的说明请见[drawing_image_filter.h](../reference/apis-arkgraphics2d/capi-drawing-image-filter-h.md)。 347 348目前只支持两种图像滤波器: 349 350- 基于颜色滤波器的图像滤波器。 351 可通过OH_Drawing_ImageFilterCreateFromColorFilter()接口实现,接口接受2个参数,颜色滤波器colorFilter和图像滤波器input,即把颜色滤波器的效果叠加到图像滤波器input上,input可为空,input为空则只添加颜色滤波器效果。 352 353- 具有模糊效果的图像滤波器。 354 可通过OH_Drawing_ImageFilterCreateBlur()接口实现,接口接受4个参数,分别为X轴上的模糊标准差、Y轴上的模糊标准差、平铺模式和图像滤波器(input)。 355 356 最终效果即为在输入的图像滤波器(input)的基础上进行模糊化处理,即滤波器效果可叠加,input可为空,input为空则只添加模糊效果。 357 358此处以绘制矩形并使用画笔添加模糊效果的图像滤波器效果为例,关键示例和效果示意图如下所示: 359 360```c++ 361// 创建画笔 362OH_Drawing_Pen *pen = OH_Drawing_PenCreate(); 363// 设置画笔抗锯齿 364OH_Drawing_PenSetAntiAlias(pen, true); 365// 设置画笔描边颜色 366OH_Drawing_PenSetColor(pen, 0xffff0000); 367// 设置画笔线宽 368OH_Drawing_PenSetWidth(pen, 20); 369// 创建图像滤波器实现模糊效果 370OH_Drawing_ImageFilter *imageFilter = 371 OH_Drawing_ImageFilterCreateBlur(20.0f, 20.0f, OH_Drawing_TileMode::CLAMP, nullptr); 372// 创建一个滤波器对象 373OH_Drawing_Filter *filter = OH_Drawing_FilterCreate(); 374// 为滤波器对象设置图像滤波器 375OH_Drawing_FilterSetImageFilter(filter, imageFilter); 376// 设置画笔的滤波器效果 377OH_Drawing_PenSetFilter(pen, filter); 378// 在画布上设置画笔,请确保已获取得到画布对象 379OH_Drawing_CanvasAttachPen(canvas, pen); 380// 创建矩形 381OH_Drawing_Rect *rect = OH_Drawing_RectCreate(300, 300, 900, 900); 382// 绘制矩形 383OH_Drawing_CanvasDrawRect(canvas, rect); 384// 去除掉画布中的画笔 385OH_Drawing_CanvasDetachPen(canvas); 386// 销毁各类对象 387OH_Drawing_PenDestroy(pen); 388OH_Drawing_ImageFilterDestroy(imageFilter); 389OH_Drawing_RectDestroy(rect); 390OH_Drawing_FilterDestroy(filter); 391``` 392 393| 不设置图像滤波器效果的示意图 | 设置图像滤波器效果的示意图 | 394| -------- | -------- | 395|  |  | 396 397 398### 蒙版滤波器效果 399 400蒙版滤波器的模糊效果仅对透明度和形状边缘进行模糊处理,相对于图像滤波器的模糊效果来说计算成本更低。 401 402蒙版滤波器可基于画笔或画刷实现,蒙版滤波器的相关接口和具体参数的说明请见[drawing_mask_filter.h](../reference/apis-arkgraphics2d/capi-drawing-mask-filter-h.md)。 403 404可使用OH_Drawing_MaskFilterCreateBlur()接口创建想要设置具有模糊效果的蒙版滤波器。接口接受3个参数,分别为: 405 406- blurType:用于指定要应用的模糊类型,详细分类请参考[OH_Drawing_BlurType](../reference/apis-arkgraphics2d/capi-drawing-mask-filter-h.md#oh_drawing_blurtype)。 407 408- sigma:用于指定要应用的高斯模糊的标准差,标准差必须大于0。 409 410- respectCTM:指定模糊的标准差是否会被CTM(coordinate transformation matrix,坐标变换矩阵)修改,默认为true,表示会被对应修改。 411 412此处以绘制矩形并使用画笔设置蒙版滤波器效果为例,关键示例和效果示意图如下所示: 413 414```c++ 415// 创建画笔 416OH_Drawing_Pen *pen = OH_Drawing_PenCreate(); 417// 设置画笔抗锯齿 418OH_Drawing_PenSetAntiAlias(pen, true); 419// 设置画笔描边颜色 420OH_Drawing_PenSetColor(pen, 0xffff0000); 421// 设置画笔线宽 422OH_Drawing_PenSetWidth(pen, 20); 423// 创建蒙版滤波器 424OH_Drawing_MaskFilter *maskFilter = OH_Drawing_MaskFilterCreateBlur(OH_Drawing_BlurType::NORMAL, 20, true); 425// 创建一个滤波器对象 426OH_Drawing_Filter *filter = OH_Drawing_FilterCreate(); 427// 为滤波器对象设置蒙版滤波器 428OH_Drawing_FilterSetMaskFilter(filter, maskFilter); 429// 设置画笔的滤波器效果 430OH_Drawing_PenSetFilter(pen, filter); 431// 在画布上设置画笔,请确保已获取得到画布对象 432OH_Drawing_CanvasAttachPen(canvas, pen); 433// 创建矩形 434OH_Drawing_Rect *rect = OH_Drawing_RectCreate(300, 300, 900, 900); 435// 绘制矩形 436OH_Drawing_CanvasDrawRect(canvas, rect); 437// 去除掉画布中的画笔 438OH_Drawing_CanvasDetachPen(canvas); 439// 销毁各类对象 440OH_Drawing_PenDestroy(pen); 441OH_Drawing_MaskFilterDestroy(maskFilter); 442OH_Drawing_RectDestroy(rect); 443OH_Drawing_FilterDestroy(filter); 444``` 445 446| 不设置蒙版滤波器效果的示意图 | 设置蒙版滤波器效果的示意图 | 447| -------- | -------- | 448|  |  | 449 450<!--RP1--> 451## 相关实例 452 453针对Drawing(C/C++)的开发,有以下相关实例可供参考: 454 455- [NDKGraphicsDraw (API14)](https://gitcode.com/openharmony/applications_app_samples/tree/master/code/DocsSample/Drawing/NDKGraphicsDraw) 456<!--RP1End-->