When your C++ application needs to render charts, PDFs, UI widgets, or GPU-accelerated visualizations, you need a 2D graphics library. The choice between Skia, Cairo, NanoVG, and Blend2D determines your rendering performance, output fidelity, and platform reach. This comparison covers their architectures, backends, and real-world use cases.
Library Comparison
| Feature | Skia | Cairo | NanoVG | Blend2D |
|---|---|---|---|---|
| Stars | 10,786 | 4,300+ | 5,661 | 1,947 |
| Language | C++ | C | C | C++ |
| GPU Backend | OpenGL, Vulkan, Metal | OpenGL (experimental) | OpenGL, GLES, Metal | Built-in JIT |
| CPU Backend | Raster (SW) | Pixman, Xlib, Quartz | None (GPU only) | SIMD-accelerated JIT |
| PDF Output | Yes (via SkPDF) | Yes (native) | No | No |
| SVG Output | Yes | Yes | No | No |
| Text Rendering | HarfBuzz + FreeType | Pango + FreeType | stb_truetype | Custom shaper |
| Anti-aliasing | MSAA + Analytic AA | Subpixel AA | MSAA | Analytic AA |
| Primary Users | Chrome, Flutter, Android | GTK, Inkscape, librsvg | Game UIs, tools | High-perf rendering |
Skia: The Production Powerhouse
Google’s Skia renders every pixel in Chrome, Flutter, and Android. It provides both CPU rasterization and GPU-accelerated backends (OpenGL, Vulkan, Metal). Skia’s strength is production hardening — billions of devices, constant fuzzing, and continuous performance regression testing.
| |
Skia’s API is the most comprehensive — path effects, shaders, image filters, color spaces, and color management are all first-class concepts. The build system uses GN (Google’s Ninja generator), which is unfamiliar to most C++ developers outside Google. Skia’s binary is large (~15-20 MB) and integration requires either a prebuilt binary or custom GN build.
Cairo: The Portable Standard
Cairo has been the de facto 2D graphics library for Linux desktop since 2003. GTK, librsvg, Inkscape, and WebKitGTK all rely on Cairo for rendering. It provides a consistent API across multiple backends: image buffers, PDF, PostScript, SVG, Xlib, Quartz, and Win32.
| |
Cairo’s killer feature is its PDF/PS/SVG output fidelity. The generated vector files are pristine — Inkscape uses Cairo for SVG export precisely because of this. Cairo’s limitations: GPU support is experimental (cairo-gl) and not suitable for real-time rendering. For interactive applications, CPU-only rendering tops out at ~60 FPS for simple scenes on modern hardware.
NanoVG: Lightweight GPU UI Rendering
NanoVG is a single-header C library designed for immediate-mode UI rendering on top of OpenGL. It’s not a general-purpose 2D library — it’s specifically for drawing buttons, sliders, graphs, and text in real-time applications.
| |
NanoVG is perfect for game UIs, audio plugin interfaces, and embedded device screens where you need 60 FPS with minimal dependencies. Its limitations: no PDF/SVG output, no CPU-only fallback, and limited text layout (no RTL, complex script shaping). For data visualization dashboards running in embedded contexts, NanoVG’s simplicity is a feature rather than a limitation.
Blend2D: JIT-Accelerated Vector Graphics
Blend2D takes a unique approach: it compiles rendering pipelines to native code at runtime using its own JIT compiler (AsmJit). This means Blend2D generates CPU-specific vectorized code for each drawing operation, achieving near-GPU speeds on the CPU.
| |
Blend2D’s JIT compilation makes it the fastest CPU-based 2D renderer — in benchmarks, it renders complex vector scenes 3-5x faster than Cairo and 2-3x faster than Skia’s CPU rasterizer. The trade-offs: immature compared to Skia/Cairo, smaller community, and the JIT compilation adds a one-time initialization cost. Blend2D is ideal for headless rendering pipelines where GPU access is limited or you want to avoid GPU driver complexity.
Performance Benchmarks
Rendering a complex scene (500 paths, 200 gradient fills, 50 text strings) at 1920x1080:
| Library | CPU Time (ms) | GPU Time (ms) | Memory (MB) | Output Formats |
|---|---|---|---|---|
| Skia (GPU) | 2.1 | 0.8 | 32 | PNG, PDF, SVG |
| Skia (CPU) | 14.2 | N/A | 28 | PNG, PDF, SVG |
| Cairo | 38.5 | N/A | 18 | PNG, PDF, SVG, PS |
| NanoVG | 1.8 | 0.6 | 10 | Framebuffer only |
| Blend2D | 5.8 | N/A | 22 | PNG, raw pixels |
For real-time GPU rendering, NanoVG and Skia are the clear winners. For PDF/SVG generation, Cairo produces the most standards-compliant output. Blend2D offers the best CPU-only performance — ideal for server-side rendering pipelines where GPUs aren’t available.
Self-Hosting 2D Rendering Pipelines
Server-side rendering is increasingly common. Dashboards-as-image, chart generation APIs, and PDF report generators all run 2D rendering headlessly. Cairo and Skia excel here because they don’t require a GPU. Blend2D’s JIT approach makes it the fastest pure-CPU option for high-throughput rendering services.
For context on how these libraries relate to UI frameworks, see our C++ immediate-mode GUI comparison. For algorithms that drive rendering pipelines, see our graph algorithm libraries comparison. For serialization of rendered assets, check our C++ serialization libraries guide.
Integration with Application Frameworks
Each 2D library integrates differently with windowing systems and application frameworks. Understanding these integration patterns is essential for production deployment.
With Skia, the recommended path on Linux is GLFW for window creation paired with Skia’s GrDirectContext::MakeGL() for GPU rendering. On macOS, use SkMetalSurface with a Metal layer from NSView. For Flutter-based projects, Skia is already embedded in the engine, requiring no additional integration work.
Cairo integrates natively with GTK through gdk_cairo_create() for GTK applications. For Qt projects, QPainter wraps Cairo on Linux platforms. Cairo’s image surface (cairo_image_surface_create) provides a simple framebuffer for headless rendering — ideal for PDF generation services that don’t need a display.
NanoVG pairs with GLFW (nvgCreateGL3) or SDL2 for window management. For ImGui-based interfaces, NanoVG can render behind ImGui draw lists, combining the strengths of both libraries. On embedded Linux (Yocto, Buildroot), NanoVG with EGL/GLES provides a lightweight rendering stack without X11 dependencies.
Blend2D produces BLImage objects that can be converted to common formats. For Qt integration, convert Blend2D’s output to QImage using BLImage::getData() and QImage’s raw data constructor. For web services, encode Blend2D output to PNG using its built-in codec and serve via HTTP. Blend2D’s JIT compiler requires write+execute memory pages (mmap with PROT_WRITE | PROT_EXEC), which may need SELinux policy adjustments in containerized deployments.
Build System Integration
All four libraries integrate with CMake, but with different levels of convenience:
| |
For Docker container deployments, Cairo and Blend2D are the easiest to containerize — they need only a C++ runtime and standard system libraries. Skia requires the larger GN build toolchain unless using prebuilt binaries. NanoVG needs an OpenGL context, which works with Mesa’s software rasterizer (LIBGL_ALWAYS_SOFTWARE=1) for headless environments.
FAQ
Can I use Skia without building Chromium’s entire toolchain?
Yes. Google provides prebuilt Skia binaries through the Skia Infra (CIPD packages) and community-maintained Conan/vcpkg ports. The simplest path is conan install skia/126. However, if you need a custom configuration (disabling codecs, enabling Vulkan), you’ll need to build from source with GN. The build takes 15-30 minutes on a modern machine.
Does Cairo support GPU rendering?
Cairo’s OpenGL backend (cairo-gl) exists but is experimental. It accelerates fills and blits but doesn’t match Skia’s GPU performance. For production GPU rendering, use Skia or NanoVG. Cairo’s strength is software rendering with guaranteed pixel-identical output across platforms.
Is NanoVG suitable for production monitoring dashboards?
Yes, if your dashboard is a real-time native application. NanoVG pairs well with GLFW or SDL for creating monitoring UIs that update at 60 FPS with animated graphs. However, it cannot export PDF reports or PNG snapshots without an additional framebuffer-to-image step.
How does Blend2D’s JIT compilation work?
At the first drawing call, Blend2D’s JIT compiler (based on AsmJit) generates x86/ARM machine code specialized for your CPU’s SIMD width (SSE4, AVX2, AVX-512, NEON). Subsequent calls execute this generated code directly, bypassing the interpreter. The first frame is ~50ms slower due to compilation; subsequent frames run at full speed.
What’s the best library for server-side PDF generation?
Cairo. Its PDF output is pixel-perfect and standards-compliant. Skia’s PDF output (SkPDF) is also excellent but requires more configuration. For high-throughput PDF generation where every millisecond counts, Blend2D + a PDF encoder library (like libharu) can be faster, but the output quality won’t match Cairo’s typographic fidelity.
💡 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com