资讯详情

资讯详情

SkiaSharp.Views.Gtk3 的 SKDrawingArea:在 GTK3 桌面应用中集成 SkiaSharp 绘图画布

图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载本指南以 SkiaSharp 1.68.1 版本中SkiaSharp.Views.Gtk3.dll的 API 变更记录为线索系统讲解SkiaSharp.Views.Gtk.SKDrawingArea这一 GTK3 绘图控件的完整用法包括控件类签名、PaintSurface事件与OnPaintSurface两种绘制入口、CanvasSize的像素语义以及它与 Cairo 渲染管线之间的桥接原理。阅读本文后你将能够在 GtkSharp 3 桌面程序中直接嵌入 SkiaSharp 画布绘制矢量图形、位图与文本并借助类型转换扩展在 SkiaSharp 与 GTK 数据类型之间自由切换。一、背景1.68.1 版本中的新命名空间与新类型在 SkiaSharp 1.68.1 的发布说明API diff: SkiaSharp.Views.Gtk3.dll中SkiaSharp.Views.Gtk3.dll程序集版本由0.0.0.0变更为1.68.0.0并新增了一个命名空间新命名空间SkiaSharp.Views.Gtk新类型SkiaSharp.Views.Gtk.SKDrawingArea这意味着从该版本起GTK3 桌面应用获得了官方的一等公民绘图控件SKDrawingArea。它继承自 GtkSharp 的标准绘图控件Gtk.DrawingArea同时通过实现Atk.IImplementor、GLib.IWrapper、System.IDisposable等接口融入 GTK 对象体系其源码实现位于 source/SkiaSharp.Views/SkiaSharp.Views.Gtk3/SKDrawingArea.cs。public class SKDrawingArea : Gtk.DrawingArea, Atk.IImplementor, GLib.IWrapper, System.IDisposable { // constructors public SKDrawingArea (); // properties public SkiaSharp.SKSize CanvasSize { get; } // events public event System.EventHandlerSkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs PaintSurface; // methods protected override void Dispose (bool disposing); protected override bool OnDrawn (Cairo.Context cr); protected virtual void OnPaintSurface (SkiaSharp.Views.Desktop.SKPaintSurfaceEventArgs e); }该控件位于独立的程序集SkiaSharp.Views.Gtk3RootNamespace为SkiaSharp.Views.Gtk其工程文件见 source/SkiaSharp.Views/SkiaSharp.Views.Gtk3/SkiaSharp.Views.Gtk3.csproj。工程通过PackageReference引用GtkSharp 3.24.24.95并依赖核心库SkiaSharp与桌面公共程序集SkiaSharp.Views.Desktop.Common因此绘制事件参数SKPaintSurfaceEventArgs来自SkiaSharp.Views.Desktop命名空间。二、项目引用与运行环境要在自己的 GTK3 应用中启用该控件需要准备三部分依赖GtkSharp 3通过 NuGet 包GtkSharp 3.24.24.95引入该版本号与 SkiaSharp.Views.Gtk3 工程锁定的版本一致。SkiaSharp 核心库提供SKSurface、SKCanvas、SKImageInfo等绘图基础设施。SkiaSharp.Views.Gtk3 程序集即本文主角同时会连带引入SkiaSharp.Views.Desktop.Common。仓库中的示例工程 samples/Basic/Gtk3/SkiaSharpSample/SkiaSharpSample.csproj 展示了完整的引用方式OutputType为WinExe目标框架为net10.0直接以ProjectReference引用上述程序集并通过IncludeNativeAssets.SkiaSharp.targets见 binding/IncludeNativeAssets.SkiaSharp.targets将对应平台的libSkiaSharp原生库复制到输出目录。运行还需要系统级 GTK3 开发库macOSbrew install gtk3Ubuntu/Debiansudo apt-get install libgtk-3-devFedorasudo dnf install gtk3-develLinux 下构建运行示例dotnet run --project SkiaSharpSample/SkiaSharpSample.csproj说明GTK 3 不提供 GPU 加速的 SkiaSharp 视图SKDrawingArea走的是 CPU 软件渲染路径这一点在 samples/Basic/Gtk3/README.md 中有明确说明。三、SKDrawingArea 的两种绘制方式SKDrawingArea源码的 XML 文档明确指出在该画布上绘图有两种等价的方式见 SKDrawingArea.cs订阅PaintSurface事件适用于大多数场景尤其是 UI 代码与绘制逻辑分离时。重写OnPaintSurface虚方法适用于子类化控件、封装自定义绘制逻辑的场景。PaintSurface事件类型为EventHandlerSKPaintSurfaceEventArgs其中SKPaintSurfaceEventArgs定义在 source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs提供三个关键成员成员类型含义SurfaceSKSurface当前正在绘制的 SkiaSharp 表面通过Surface.Canvas获得画布InfoSKImageInfo表面信息Info.Width/Info.Height即画布像素尺寸RawInfoSKImageInfo底层表面的原始图像信息实际尺寸与颜色类型事件方式的最小绘制模板myView.PaintSurface (sender, e) { var surface e.Surface; var surfaceWidth e.Info.Width; var surfaceHeight e.Info.Height; var canvas surface.Canvas; // draw on the canvas canvas.Flush (); };重写OnPaintSurface的方式protected override void OnPaintSurface (SKPaintSurfaceEventArgs e) { // call the base method base.OnPaintSurface (e); var surface e.Surface; var surfaceWidth e.Info.Width; var surfaceHeight e.Info.Height; var canvas surface.Canvas; // draw on the canvas canvas.Flush (); }[!IMPORTANT] 如果重写了OnPaintSurface必须调用base.OnPaintSurface(e)否则PaintSurface事件将不会被触发。这一点在控件源码的 XML 注释中被标记为重要注意事项SKDrawingArea.cs其实现也印证了调用关系OnPaintSurface的默认实现就是PaintSurface?.Invoke(this, e)SKDrawingArea.cs。两种方式都在 GTK 控件重绘时被调用即由OnDrawn(Cairo.Context cr)驱动下文详述因此绘制是按需触发的——当窗口尺寸变化、被遮挡后重新显示或显式调用QueueDraw()时GTK 会请求重绘进而触发绘制回调。四、CanvasSize 属性与像素密度语义CanvasSize返回类型为SkiaSharp.SKSize其文档注释说明了关键语义SKDrawingArea.csThe canvas size may be different to the view size as a result of the current devices pixel density.即画布尺寸像素可能与控件尺寸逻辑单位不一致因为高分屏HiDPI下存在像素密度换算。源码实现为public SKSize CanvasSize pix null ? SKSize.Empty : new SKSize(pix.Width, pix.Height);其中pix是内部持有的 CairoImageSurface。当控件尚未完成首次分配pix为null时返回SKSize.Empty否则返回底层像素缓冲的实际宽高。在示例 DrawingPage.cs 中可以看到处理这一差异的典型手法——用e.Info.Width / skiaView.AllocatedWidth计算缩放系数并canvas.Scale(sx, sy)从而让逻辑坐标与控件坐标保持一致。五、渲染管线从 GTK Drawn 事件到 SkiaSharp 表面SKDrawingArea的核心是把 SkiaSharp 的绘制结果呈现到 GTK3 的 Cairo 上下文中。理解整个流程有助于调试像素格式、HiDPI 等问题。关键路径在OnDrawn(Cairo.Context cr)SKDrawingArea.cs获取控件分配区域通过AllocationGdk.Rectangle得到控件的实际宽高。构建SKImageInfonew SKImageInfo(w, h, SKImageInfo.PlatformColorType, SKAlphaType.Premul)即使用平台默认颜色类型、预乘 alpha。创建或复用绘图对象CreateDrawingObjects()按需创建 CairoImageSurface(Format.Argb32, w, h)并通过SKSurface.Create(imgInfo, pix.DataPtr, imgInfo.RowBytes)让 SkiaSharp 直接包装 Cairo 的像素缓冲——两者共享同一块内存避免了拷贝SKDrawingArea.cs。当尺寸变化时旧的 surface 与 pixbuf 会被释放重建。触发绘制回调用SKAutoCanvasRestore包裹OnPaintSurface(new SKPaintSurfaceEventArgs(surface, imgInfo))保证绘制结束后画布状态自动恢复SKDrawingArea.cs。刷新与标记脏surface.Canvas.Flush()将 SkiaSharp 的绘制命令实际写入共享像素缓冲随后pix.MarkDirty()通知 Cairo 缓冲内容已变化。通道顺序修正RGBA ↔ ARGB32当颜色类型为Rgba8888时用SKSwizzle.SwapRedBlue交换 R/B 通道使 SkiaSharp 的 RGBA 布局适配 Cairo 的 ARGB32 内存布局SKDrawingArea.cs。呈现到 GTK 窗口cr.SetSourceSurface(pix, 0, 0)cr.Paint()把 pixbuf 画到 GTK 的 Cairo 上下文返回true表示事件已处理。注意OnDrawn收到的Cairo.Context在方法返回后即被释放因此不应在方法作用域之外持有该 Cairo 上下文的引用SKDrawingArea.cs。Dispose(bool)重写则在释放托管资源时调用FreeDrawingObjects()同步释放 Cairo pixbuf 与 SkiaSharp surfaceSKDrawingArea.cs避免原生资源泄漏。六、类型转换扩展GTKExtensions与控件同程序集的 GTKExtensions.cs 提供了一组静态扩展方法用于在 SkiaSharp 与 GTK/GDK 类型间互相转换按用途可分为四类1. 几何类型转换扩展方法方向说明Point.ToSKPointI()/SKPointI.ToPoint()Gdk.Point ↔ SKPointI点Rectangle.ToSKRectI()/SKRectI.ToRect()Gdk.Rectangle ↔ SKRectI矩形Size.ToSKSizeI()/SKSizeI.ToSize()Gdk.Size ↔ SKSizeI尺寸2. 颜色转换Color.ToSKColor()将Gdk.Color分量范围为 0~65535按65535f / 255f缩放为 0~255 的SKColor字节分量SKColor.ToColor()反向转换回Gdk.Color。3. 图像转换SK → Gdk.PixbufSKPicture.ToPixbuf(SKSizeI dimensions)先把图片栅格化为指定尺寸的SKImage再转 pixbufSKImage.ToPixbuf()创建Colorspace.Rgb、带 alpha、每像素 8 位的Pixbuf通过SKPixmap读取像素若颜色类型为Bgra8888同样执行SwapRedBlue修正通道顺序SKBitmap.ToPixbuf()与SKPixmap.ToPixbuf()经由SKImage.FromPixels中转。4. 图像转换Gdk.Pixbuf → SKPixbuf.ToSKBitmap()/Pixbuf.ToSKImage()将 GDK 像素缓冲包装为 SkiaSharp 位图或图像Pixbuf.ToSKPixmap(SKPixmap)直接把 pixbuf 像素数据拷贝进已有 pixmap并在Bgra8888下交换 R/B。这些扩展让开发者可以在 GTK 控件如Gtk.Image、Gdk.Pixbuf相关控件与 SkiaSharp 之间无缝搬运图像数据是集成时的高频工具。七、实战示例在 GTK3 应用中嵌入 SKDrawingArea仓库中的 Basic/Gtk3 示例是完整的可运行参考包含CPU 画布与自由绘画两个页面其 UI 布局由 Glade.glade文件定义、以嵌入资源方式编译见 SkiaSharpSample.csproj。由于SKDrawingArea不是 Glade 内置控件示例采用占位容器 代码注入的模式// Load layout from Glade — provides the placeholder container var builder MainWindow.LoadBuilder(SkiaSharpSample.CpuPage.glade); var page (Box)builder.GetObject(cpuPage); // Insert SKDrawingArea (custom widget not available in Glade) var skiaView new SKDrawingArea(); skiaView.PaintSurface OnPaintSurface; page.PackStart(skiaView, true, true, 0);完整代码见 samples/Basic/Gtk3/SkiaSharpSample/CpuPage.cs场景一静态场景渲染CpuPage演示了典型的事件订阅 SkiaSharp 绘制流程CpuPage.cscanvas.Clear(SKColors.White)清空画布SKShader.CreateRadialGradient创建径向渐变背景配合SKPaint { IsAntialias true, Shader shader }绘制全屏矩形canvas.DrawCircle绘制一组半透明彩色圆canvas.DrawText(SkiaSharp, ..., SKTextAlign.Center, font, textPaint)居中绘制文字。这展示了在 GTK3 中完成渐变 几何图形 文本组合渲染的最小闭环。场景二交互式自由绘画DrawingPage更进一步演示了如何让SKDrawingArea响应鼠标输入并增量重绘DrawingPage.cs注册事件掩码skiaView.AddEvents(EventMask.ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ScrollMask | EnterNotifyMask | LeaveNotifyMask)并订阅ButtonPressEvent、ButtonReleaseEvent、MotionNotifyEvent、ScrollEvent等 GTK 事件记录笔画按下时创建SKPathBuilder并MoveTo移动时LineTo抬起时将路径快照存入笔画列表按需重绘每次状态变化调用skiaView.QueueDraw()请求 GTK 重绘触发OnDrawn→PaintSurface的渲染管线绘制回放在OnPaintSurface中先清空画布再逐条回放strokes列表中的路径实现笔画在改色、调粗细后依然保留。其中e.Info.Width / skiaView.AllocatedWidth的坐标缩放、滚动滚轮调整笔刷大小ScrollDirection.Smooth与DeltaY判断都是 GTK3 SkiaSharp 集成中的实用细节。八、版本与适用前提小结项目值程序集SkiaSharp.Views.Gtk3.dll1.68.1 起程序集版本 1.68.0.0命名空间SkiaSharp.Views.Gtk依赖GtkSharp 3.24.24.95、SkiaSharp、SkiaSharp.Views.Desktop.Common渲染方式CPU 软件渲染GTK3 无 GPU 加速视图参考示例samples/Basic/Gtk3相关测试GTK 4 版本存在对应的SKDrawingAreaTest与GTKExtensionsTest见 tests/SkiaSharp.Views.Gtk4.Tests可作行为参考从 API 变更记录到源码实现再到示例工程SKDrawingArea构成了 GTK3 桌面应用接入 SkiaSharp 的完整链路Gtk.DrawingArea负责窗口集成与事件分发CairoImageSurface提供共享像素缓冲SKSurface提供高性能的 2D 绘制 APIGTKExtensions则打通了两套类型系统。掌握这些机制后你便可以在 GTK3 应用中自由使用 SkiaSharp 的完整绘图能力。赞分享图形学图像处理跨平台【免费下载链接】SkiaSharpSkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Googles Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.项目地址https://gitcode.com/gh_mirrors/sk/SkiaSharp点击查看免费下载相关推荐解读 SkiaSharp GTK 视图的完整 API 面从 1.60.0 引入的 SKWidget 到现代 SKDrawingArea解读 SkiaSharp GTK 视图的完整 API 面从 1.60.0 引入的 SKWidget 到现代 SKDrawingArea 本篇基于 SkiaSh图形学图像处理跨平台Synergy-core与云桌面集成在远程桌面环境中的应用Synergy core与云桌面集成在远程桌面环境中的应用 Synergy core作为开源的跨平台键盘鼠标共享工具正在成为云桌面和远程办公环境中的重要技术桌面应用网络通信Anime.js桌面应用Electron集成动画方案Anime.js桌面应用Electron集成动画方案 痛点桌面应用动画开发的挑战 你是否在为桌面应用寻找高性能的动画解决方案传统Web动画在Electro前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →