- 图形学
- 桌面应用
【免费下载链接】RGF_CJ
RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。
位图画刷(BitmapBrush)是 RGF 渲染框架中一种以图片内容作为填充源的设备相关资源,在掌握位图加载与图层绘制之后,即可基于二者创建位图画刷,进而实现图片的重复平铺、区域填充等批量渲染效果。本文将以 RGF_CJ 官方教程第十一课为骨架,结合仓库源码与测试用例,完整讲解位图画刷的成员声明、两种创建方式、底层分发原理、填充绘制与资源释放,帮助你在仓颉 Windows 应用开发中直接落地使用。
位图画刷概述
在 RGF_CJ 中,画刷是绘制图形时必不可少的“颜料源”。与纯色画刷用单一颜色填充不同,位图画刷将一张位图或一个图层的内容作为填充源,绘制时可以把图片“刷”到矩形、椭圆、圆角矩形等目标区域中,并支持基于图片内容的重复平铺。
位图画刷在源码中定义于 src/rgf_core/rgf_brush_bitmap.cj,其类型层级如下:
public open class BitmapBrush <: Brush{ public init(){ super(CPointer<Unit>()) } internal init(oPtr:CPointer<Unit>){ super(oPtr) } ... }BitmapBrush继承自画刷父类Brush(定义于 src/rgf_core/rgf_brush.cj),因此天然具备Brush提供的线宽读取与设置能力(getLineWidth()/setLineWidth())。- 从注释可知,位图画刷属于设备相关资源,即其生命周期与底层图形设备(窗口渲染表面
surface)绑定,需要遵循 RGF 的资源创建与释放约定。
创建位图画刷
第一步:声明画刷成员
与位图、图层等设备相关资源一样,位图画刷需要先作为窗口类的成员存在。使用@LifeCycle宏后,框架会自动接管类成员资源的管理(自动构造与自动释放),无需再手动初始化:
@LifeCycle class WinSelf <: WinCore{ let bmpBrh:BitmapBrush }补充说明:
@LifeCycle宏只接管类成员的自动化管理;对于函数内部临时创建的设备相关资源,仍需在结束后手动调用release()释放(详见下文“资源释放”小节,该约定同样适用于位图画刷)。
方式一:从位图创建位图画刷
位图画刷最常见的来源是一张已加载的位图。先通过渲染表面surface的createBitmap()从本地图片文件创建位图,再基于该位图对象创建画刷:
public override func createDeviceResources():Bool{ // 从文件创建位图对象 let bmp:Bitmap = surface.createBitmap("./res/test.png") // 基于位图对象创建位图画刷 surface.createBitmapBrush(bmpBrh,bmp) // 释放临时的位图对象 bmp.release() return true; }要点说明:
- 路径支持相对路径,示例中的
"./res/test.png"对应仓库 res/test.png;RGF_CJ目前支持JPEG、PNG等常用图片格式(参见第七课《加载并渲染图片》)。 - 从文件创建位图时,底层实现会将字符串路径转换为宽字符串并调用
rApiDctClassCreateBitmapFromFile(见 src/rgf_core/rgf_renderer.cj)。 - 位图对象只是创建画刷的临时载体,画刷创建完成后即调用
bmp.release()释放,避免设备相关资源泄漏。
方式二:从图层创建位图画刷
如果你需要以一段“绘制好的内容”作为填充源(例如预先在图层里画好的图案),可以先把内容绘制进一个图层,再把整个图层交给位图画刷:
public override func createDeviceResources():Bool{ // 创建一个 10*10 的图层 let lay:Layer = surface.createLayer(10,10) lay.draw{=> // 在图层中绘制些什么 } // 基于图层对象创建位图画刷 surface.createBitmapBrush(bmpBrh,lay) // 释放临时的图层对象 lay.release() return true; }要点说明:
- 图层通过
surface.createLayer(width, height)创建,该接口定义于 src/rgf_core/rgf_draw_creater.cj。 Layer类型(src/rgf_core/rgf_layer.cj)同时实现了Image与IDraw接口,因此图层既可作为图像源(Image),也可像渲染表面一样承载绘制操作(IDraw,支持drawLine、drawRectangle、drawBitmap等方法)。- 图层内的一切绘制都应包裹在
lay.draw{=> ... }中执行(唯一的例外是onPaint()中surface、bindSurface可直接绘制而无需嵌套draw()),这一约定在第十课《更多的图层》中有明确说明。 - 同样地,图层对象用完即释放。
底层原理:按图像类型自动分发
为什么createBitmapBrush既能接收位图又能接收图层?从接口定义(src/rgf_core/rgf_draw_creater.cj)可以看到,createBitmapBrush的参数类型统一为Image——而Bitmap与Layer都继承自Image。在 src/rgf_core/rgf_renderer.cj 的实现中,框架会根据实际传入对象的子类型(SfcSubObjType.Bitmap或SfcSubObjType.Layer)分别调用底层对应的原生创建接口:
public func createBitmapBrush (img:Image):BitmapBrush{ if(!isValid() || !img.isValid()){ throw Exception(rgfErrorCpluapluaObjNotExist) } if(img.objType == SfcSubObjType.Bitmap){ return BitmapBrush(unsafe{ rApiDctClassCreateBitmapBrush(objPtr,img.objPtr) }) }else if(img.objType == SfcSubObjType.Layer){ return BitmapBrush(unsafe{ rApiDctClassCreateBitmapBrushLay(objPtr,img.objPtr) }) } throw Exception(rgfErrorCpluapluaObjNotExist) }由此可以推断:位图画刷的“内容源”本质上就是一张图像(位图或图层),这也是它能实现“基于图片内容重复平铺”的根源。另外注意,若传入的Image既不是位图也不是图层,或底层对象尚未创建,接口会抛出rgfErrorCpluapluaObjNotExist异常。
使用位图画刷
创建好的画刷要在绘制方法中发挥价值。surface渲染表面提供了大量以fill和draw开头的绘制方法——前者表示填充、后者表示描边(该语义约定见第五课《使用纯色画刷》),这些方法通常都需要一个画刷参数。以绘制矩形为例:
public override func onPaint(wRect:Rect):Unit{ surface.clear(1.0,1.0,1.0,1.0) // 获取渲染表面矩形 var rect:Rect = surface.getRect() rect = Rect( rect.left + 10, rect.top + 10, rect.right - 10, rect.bottom - 10 ) // 绘制矩形 surface.fillRectangle(rect,bmpBrh) }代码解读:
surface.clear(1.0, 1.0, 1.0, 1.0)将窗口清为不透明白色;surface.getRect()获取渲染表面(窗口客户区)的矩形范围;- 随后构造一个四周各缩进 10 单位的矩形,使填充区域与窗口边缘保留 10 单位的留白;
surface.fillRectangle(rect, bmpBrh)用位图画刷填充该矩形区域,填充内容即画刷所承载的图片/图层。
fillRectangle在 src/rgf_core/rgf_renderer.cj 中提供了(x, y, width, height)、FRect、Rect三种重载形式,最终统一调用底层rApiDttClassFillRectangle完成填充。同理,fillEllipse、fillRoundedRectangle等填充方法也都可以搭配位图画刷使用,以填充圆形、圆角矩形等目标区域。
调试运行程序,即可看到位图画刷填充的效果:
资源释放与生命周期管理
位图画刷属于设备相关资源,其释放遵循 RGF 的统一约定:
- 类成员:搭配
@LifeCycle宏使用时,框架自动接管创建与释放,无需(也不要)在destroyDeviceResources()中手动调用release(); - 函数内临时对象:如在
createDeviceResources()中临时创建的位图、图层等载体对象,用完后应立即release()(如前述示例中的bmp.release()/lay.release())。
从底层实现看,release()定义于 src/rgf_core/rgf_base.cj,它调用原生释放接口后将内部指针置空,使对象失效;重复调用是安全的。若在对象已释放后继续调用涉及底层对象的方法,会抛出“对象不存在”异常。
测试用例中的真实用法
在仓库的集成测试 test/HLT/base/src/test_win.cj 中,可以看到位图画刷与图层组合使用的完整场景——先创建图层,再从文件加载位图、创建位图画刷,最后在图层中绘制:
layer = surface.createLayer(210, 210); let img:Bitmap = surface.createBitmap("./res/test.png"); imgBrush = surface.createBitmapBrush(img); // 可以使用尾随lambda绘制 layer.draw(){=> layer.drawPath(path,slbbrush) layer.drawBitmap(0.0, 0.0, 210.0, 210.0, img, 0.0, 0.0, 210.0, 210.0,alpha:0.5) } surface.resetLayerSize(layer,200,200)这段代码印证了两个实战要点:
createBitmapBrush(img)可以直接接收createBitmap(uri)的返回值(返回值式创建);- 位图画刷与图层、路径、位图渲染等能力可以自由组合,绘制逻辑统一收敛在
draw()中。
小结
本文围绕 RGF_CJ 位图画刷的完整使用链路展开:BitmapBrush继承自Brush,属于设备相关资源;创建时既可以从文件位图(createBitmap→createBitmapBrush)而来,也可以从图层(createLayer→ 图层内绘制 →createBitmapBrush)而来,底层会按Bitmap/Layer子类型自动分发到对应的原生创建接口;使用时配合fillRectangle等填充方法即可实现基于图片内容的区域填充与平铺渲染。掌握位图画刷后,你便可以在 RGF 应用中用图片素材驱动图形界面的批量填充效果,为后续学习渐变画刷、文本渲染与矩阵变换打下坚实基础。
- 图形学
- 桌面应用
【免费下载链接】RGF_CJ
RGF是仓颉Windows系统下的通用渲染框架(兼应用开发框架)。RGF仓颉版(后续简称"RGF")基于RGF(C/C++版)封装优化而来。RGF为开发者提供轻量化、安全、高性能以及高度一致性的2D渲染能力以及常用的桌面应用开发工具,并且提供对接Direct3D的相关接口,以满足开发者对3D画面渲染的需求。在Windows开发方面,RGF在子包内也提供开箱即用的Windows API,确保熟悉Win32的开发者快速上手。此外,RGF还提供一些常用功能的封装(如XAudio2、MF),以辅助开发者实现音频、摄像头等扩展功能的管理。
相关推荐
RGF 仓颉版 BitmapBrush 位图画刷:类定义、创建链路与平铺填充实战
RGF 仓颉版 BitmapBrush 位图画刷:类定义、创建链路与平铺填充实战 BitmapBrush (位图画刷)是 RGF 仓颉版 rgf.rgf_cor
图形学桌面应用DGCharts CombinedChart指南:如何在一个视图里混合5种图表类型
DGCharts CombinedChart指南:如何在一个视图里混合5种图表类型 DGCharts (Charts)是为 iOS/tvOS/macOS 打造的
图形学桌面应用RGF 仓颉版 SolidColorBrush 纯色画刷:API 详解与渲染实战指南
RGF 仓颉版 SolidColorBrush 纯色画刷:API 详解与渲染实战指南 SolidColorBrush(纯色画刷)是 RGF 仓颉版(RGF_CJ
图形学桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考