Rust SVG渲染库librsvg的使用,librsvg提供高效矢量图形处理和SVG文件渲染功能

Rust SVG渲染库librsvg的使用

librsvg是一个用于渲染可缩放矢量图形(SVG)的小型库,与GNOME项目相关联。它将SVG文件渲染到Cairo表面。Cairo是GNOME用来绘制屏幕内容或生成打印输出的2D抗锯齿绘图库。

主要特点

  • 提供高效矢量图形处理和SVG文件渲染功能
  • 使用Cairo作为渲染后端
  • 支持SVG1.1和SVG2标准
  • 主要用于静态SVG渲染,不支持动画
  • 被GNOME项目广泛使用,用于渲染图标和桌面矢量图像

安装

在Cargo.toml中添加依赖:

librsvg = "2.60.0"

或者运行命令:

cargo add librsvg

系统依赖

librsvg依赖以下非Rust库:

  • Cairo - 主要渲染库
  • FreeType2 - 字体渲染器
  • gio/glib - I/O原语和流
  • Harfbuzz - 文本整形
  • libxml2 - XML解析器
  • Pangocairo - 文本渲染
  • PangoFT2 - 通过Pango和FreeType2渲染文本
  • Fontconfig - 系统字体和使用规则

使用示例

下面是一个完整的示例,展示如何使用librsvg加载和渲染SVG文件:

use librsvg::{CairoRenderer, Loader, LoadingError, RenderingError};
use cairo::{Context, Format, ImageSurface};

fn render_svg_to_png(svg_path: &str, output_path: &str, width: i32, height: i32) -> Result<(), Box<dyn std::error::Error>> {
    // 创建加载器
    let loader = Loader::new()?;
    
    // 加载SVG文件
    let svg = loader.read_file(svg_path)?;
    
    // 创建Cairo图像表面
    let surface = ImageSurface::create(Format::ARgb32, width, height)?;
    let cr = Context::new(&surface)?;
    
    // 获取渲染器
    let renderer = CairoRenderer::new(&svg);
    
    // 渲染SVG到Cairo表面
    renderer.render_document(
        &cr,
        &cairo::Rectangle::new(0.0, 0.0, width as f64, height as f64)
    )?;
    
    // 保存为PNG文件
    let mut file = std::fs::File::create(output_path)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

fn main() {
    match render_svg_to_png("input.svg", "output.png", 800, 600) {
        Ok(_) => println!("SVG rendered successfully!"),
        Err(e) => eprintln!("Error rendering SVG: {}", e),
    }
}

完整示例代码

下面是一个扩展的完整示例,包含错误处理和自定义尺寸设置:

use librsvg::{CairoRenderer, Loader};
use cairo::{Context, Format, ImageSurface};
use std::path::Path;

// 渲染SVG到PNG文件的高级函数
fn render_svg(
    input_path: impl AsRef<Path>,
    output_path: impl AsRef<Path>,
    width: u32,
    height: u32,
) -> Result<(), Box<dyn std::error::Error>> {
    // 创建SVG加载器
    let loader = Loader::new()?;
    
    // 加载SVG文件
    let svg = loader.read_file(input_path)?;
    
    // 创建Cairo图像表面
    let surface = ImageSurface::create(Format::ARgb32, width as i32, height as i32)?;
    let cr = Context::new(&surface)?;
    
    // 创建渲染器并设置DPI(默认是90dpi)
    let renderer = CairoRenderer::new(&svg)
        .dpi(96.0); // 设置96dpi以获得更精确的渲染
    
    // 渲染文档到指定尺寸
    renderer.render_document(
        &cr,
        &cairo::Rectangle::new(0.0, 0.0, width as f64, height as f64),
    )?;
    
    // 将结果保存为PNG
    let mut output_file = std::fs::File::create(output_path)?;
    surface.write_to_png(&mut output_file)?;
    
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 输入输出文件路径
    let input_svg = "example.svg";
    let output_png = "output.png";
    
    // 检查输入文件是否存在
    if !Path::new(input_svg).exists() {
        eprintln!("错误: 输入文件 {} 不存在", input_svg);
        std::process::exit(1);
    }
    
    // 渲染为800x600的PNG
    render_svg(input_svg, output_png, 800, 600)?;
    
    println!("SVG已成功渲染为PNG: {}", output_png);
    
    Ok(())
}

代码说明

  1. 创建Loader实例来加载SVG文件
  2. 使用read_file方法读取SVG文件
  3. 创建Cairo的ImageSurface作为渲染目标
  4. 设置DPI(每英寸点数)以获得更精确的渲染
  5. 调用render_document方法将SVG渲染到Cairo表面
  6. 最后将结果保存为PNG文件
  7. 添加了输入文件存在性检查

适用场景

librsvg非常适合以下场景:

  • 需要将SVG渲染为位图的应用程序
  • 图标渲染系统
  • 文件管理器中的SVG缩略图生成
  • 图像查看器中的SVG支持

注意事项

librsvg不支持以下功能:

  • SVG动画
  • 脚本或对SVG DOM的外部访问
  • 基于CSS的动画
  • 替代现代浏览器中的SVG渲染引擎

如需更复杂的SVG处理功能,可能需要考虑其他更全面的库。


1 回复

Rust SVG渲染库librsvg的使用指南

librsvg是一个高效的Rust库,用于处理和渲染SVG(可缩放矢量图形)文件。它提供了将SVG内容渲染到各种目标(如内存缓冲区或Cairo表面)的功能。

主要特性

  • 完整的SVG 1.1规范支持
  • 部分SVG 2.0功能支持
  • 高性能的矢量图形渲染
  • 支持CSS样式
  • 跨平台支持

基本使用方法

首先,在Cargo.toml中添加依赖:

[dependencies]
librsvg = "2.0"

示例1:加载并渲染SVG文件

use librsvg::{Loader, LoadingError, RenderingError};

fn render_svg_to_png(input_file: &str, output_file: &str) -> Result<(), Box<dyn std::error::Error>> {
    // 创建加载器
    let loader = Loader::new();
    
    // 加载SVG文件
    let svg = loader.read_path(input_file)?;
    
    // 获取SVG的原始尺寸
    let dimensions = svg.intrinsic_dimensions();
    let width = dimensions.width().unwrap_or(100.0);
    let height = dimensions.height().unwrap_or(極度100.0);
    
    // 创建Cairo图像表面
    let surface = cairo::ImageSurface::create(
        cairo::Format::ARgb32,
        width.ceil() as i32,
        height.ceil() as i32,
    )?;
    
    let cr = cairo::Context::new(&surface)?;
    
    // 渲染SVG到表面
    svg.render_document(
        &cr,
        &cairo::Rectangle::new(0.0, 0.0, width, height),
    )?;
    
    // 保存为PNG文件
    let mut file = std::fs::File::create(output_file)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

示例2:从内存数据加载SVG

use librsvg::{Loader, LoadingError};

fn render_from_memory(svg_data: &[u8]) -> Result<(), LoadingError> {
    let loader = Loader::new();
    let svg = loader.read_data(svg_data)?;
    
    // 这里可以进行渲染操作...
    Ok(())
}

示例3:调整渲染尺寸

use librsvg::{Loader, RenderingError};

fn render_resized(input_file: &str, output_file: &str, new_width: f64, new_height: f64) -> Result<(), Box<dyn std::error::Error>> {
    let loader = Loader::new();
    let svg = loader.read_path(input_file)?;
    
    let surface = cairo::ImageSurface::create(
        cairo::Format::ARgb32,
        new_width as i32,
        new_height as i32,
    )?;
    
    let cr = cairo::Context::new(&surface)?;
    
    // 缩放上下文以适应新尺寸
    let dimensions = svg.intrinsic_dimensions();
    let orig_width = dimensions.width().unwrap_or(1.0);
    let orig_height = dimensions.height().unwrap_or(1.0);
    
    let x_scale = new_width / orig_width;
    let y_scale = new_height / orig_height;
    cr.scale(x_scale, y_scale);
    
    svg.render_document(
        &cr,
        &cairo::Rectangle::new(0.极0, 0.0, orig_width, orig_height),
    )?;
    
    let mut file = std::fs::File::create(output_file)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

高级功能

自定义CSS样式

use librsvg::{Loader, CssProvider};

fn render_with_custom_style(input_file: &str, output_file: &str) -> Result<(), Box<dyn std::error::Error>> {
    let loader = Loader::new();
    let mut svg = loader.read_path(input_file)?;
    
    // 创建CSS提供器并添加自定义样式
    let css_provider = CssProvider::new();
    css_provider.load_from_data(".my-class { fill: #ff0000; }")?;
    
    // 将CSS提供器附加到SVG
    svg.set_stylesheet(&css_provider);
    
    // 正常渲染...
    let surface = cairo::ImageSurface::create(
        cairo::Format::ARgb32,
        100,
        100,
    )?;
    
    let cr = cairo::Context::new(&surface)?;
    svg.render_document(
        &cr,
        &cairo::Rectangle::new(0.0, 0.0, 100.0, 100.0),
    )?;
    
    let mut file = std::fs::File::create(output_file)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

完整示例代码

use librsvg::{Loader, CssProvider};
use cairo::{Context, ImageSurface, Format};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1:基本SVG渲染
    basic_render("input.svg", "output.png")?;
    
    // 示例2:从内存加载SVG
    let svg_data = std::fs::read("input.svg")?;
    let _svg_handle = load_from_memory(&svg_data)?;
    
    // 示例3:调整尺寸渲染
    render_resized("input.svg", "resized.png", 200.0, 200.0)?;
    
    // 示例4:自定义样式渲染
    render_with_style("input.svg", "styled.png", ".rect { fill: #00ff00; }")?;
    
    Ok(())
}

fn basic_render(input: &str, output: &str) -> Result<(), Box<dyn std::error::Error>> {
    let loader = Loader::new();
    let svg = loader.read_path(input)?;
    
    let dimensions = svg.intrinsic_dimensions();
    let width = dimensions.width().unwrap_or(100.0);
    let height = dimensions.height().unwrap_or(100.0);
    
    let surface = ImageSurface::create(Format::ARgb32, width.ceil() as i32, height.ceil() as i32)?;
    let cr = Context::new(&surface)?;
    
    svg.render_document(&cr, &cairo::Rectangle::new(0.0, 0.0, width, height))?;
    
    let mut file = std::fs::File::create(output)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

fn load_from_memory(data: &[u8]) -> Result<(), librsvg::LoadingError> {
    let loader = Loader::new();
    let _svg = loader.read_data(data)?;
    Ok(())
}

fn render_resized(input: &str, output: &str, new_width: f64, new_height: f64) -> Result<(), Box<dyn std::error::Error>> {
    let loader = Loader::new();
    let svg = loader.read_path(input)?;
    
    let surface = ImageSurface::create(Format::ARgb32, new_width as i32, new_height as i32)?;
    let cr = Context::new(&surface)?;
    
    let dimensions = svg.intrinsic_dimensions();
    let orig_width = dimensions.width().unwrap_or(1.0);
    let orig_height = dimensions.height().unwrap_or(1.0);
    
    cr.scale(new_width / orig_width, new_height / orig_height);
    svg.render_document(&cr, &cairo::Rectangle::new(0.0, 0.0, orig_width, orig_height))?;
    
    let mut file = std::fs::File::create(output)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

fn render_with_style(input: &str, output: &str, css: &str) -> Result<(), Box<dyn std::error::Error>> {
    let loader = Loader::new();
    let mut svg = loader.read_path(input)?;
    
    let css_provider = CssProvider::new();
    css_provider.load_from_data(css)?;
    svg.set_stylesheet(&css_provider);
    
    let surface = ImageSurface::create(Format::ARgb32, 100, 100)?;
    let cr = Context::new(&surface)?;
    
    svg.render_document(&cr, &cairo::Rectangle::new(0.0, 0.0, 100.0, 100.0))?;
    
    let mut file = std::fs::File::create(output)?;
    surface.write_to_png(&mut file)?;
    
    Ok(())
}

注意事项

  1. librsvg需要Cairo库支持,确保系统已安装Cairo
  2. 处理用户提供的SVG文件时要注意安全性,恶意SVG文件可能引发问题
  3. 对于复杂的SVG文件,渲染可能需要较多内存和CPU资源

librsvg是GNOME项目的一部分,广泛应用于Linux桌面环境,但也完全可以在其他平台上使用。它提供了高质量的SVG渲染能力,适合需要处理矢量图形的各种应用场景。

回到顶部