Rust SVG处理库typst-svg的使用,高效解析与渲染矢量图形的轻量级解决方案

Rust SVG处理库typst-svg的使用,高效解析与渲染矢量图形的轻量级解决方案

Typst是一个基于标记的排版系统,设计目标是拥有LaTeX的强大功能,同时更易于学习和使用。Typst具有以下特点:

  • 内置常见格式化任务的标记语法
  • 灵活的脚本系统
  • 数学公式排版、参考文献管理等
  • 增量编译带来的快速编译速度
  • 出错时提供友好的错误信息

Typst Logo

Typst示例

安装

可以通过以下方式安装Typst:

  1. 从GitHub releases页面下载预编译二进制文件
  2. 使用包管理器:
    • macOS: brew install typst
    • Windows: winget install --id Typst.Typst
  3. 使用Rust工具链:
    cargo install --locked typst-cli
    

使用示例

以下是Typst的一个完整示例代码:

// 设置页面大小和标题编号
#set page(width: 10cm, height: auto)
#set heading(numbering: "1.")

= Fibonacci sequence
The Fibonacci sequence is defined through the
recurrence relation $F_n = F_(n-1) + F_(n-2)$.
It can also be expressed in _closed form:_

$ F_n = round(1 / sqrt(5) phi.alt^n), quad
  phi.alt = (1 + sqrt(5)) / 2 $

// 定义变量和函数
#let count = 8
#let nums = range(1, count + 1)
#let fib(n) = (
  if n <= 2 { 1 }
  else { fib(n - 1) + fib(n - 2) }
)

// 显示结果表格
The first #count numbers of the sequence are:

#align(center, table(
  columns: count,
  ..nums.map(n => $F_#n$),
  ..nums.map(n => str(fib(n))),
))

SVG处理示例

以下是使用typst-svg处理SVG的完整示例代码:

use typst_svg::{render, scale};
use usvg::Options;

// SVG内容
let svg_data = r#"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
"#;

// 解析和渲染SVG
let tree = usvg::Tree::from_str(svg_data, &Options::default()).unwrap();
let pixmap_size = tree.size.to_screen_size();
let mut pixmap = tiny_skia::Pixmap::new(pixmap_size.width(), pixmap_size.height()).unwrap();

// 缩放SVG
let transform = scale(1.0, 1.0);
render(&tree, transform, &mut pixmap.as_mut());

// 输出PNG
pixmap.save_png("output.png").unwrap();

完整示例demo

以下是一个更完整的typst-svg使用示例,包含文件读取和错误处理:

use std::fs;
use std::path::Path;
use typst_svg::{render, scale};
use usvg::{Options, Tree};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 读取SVG文件内容
    let svg_path = Path::new("input.svg");
    let svg_data = fs::read_to_string(svg_path)?;
    
    // 2. 配置解析选项
    let options = Options {
        // 设置资源路径
        resources_dir: Some(svg_path.parent().unwrap().to_path_buf()),
        // 设置默认字体
        font_family: "Arial".to_string(),
        ..Options::default()
    };
    
    // 3. 解析SVG
    let tree = Tree::from_str(&svg_data, &options)?;
    
    // 4. 创建目标画布
    let pixmap_size = tree.size.to_screen_size();
    let mut pixmap = tiny_skia::Pixmap::new(
        pixmap_size.width(),
        pixmap_size.height()
    ).expect("Failed to create pixmap");
    
    // 5. 渲染SVG到画布
    let transform = scale(1.0, 1.0); // 不缩放
    render(&tree, transform, &mut pixmap.as_mut());
    
    // 6. 保存为PNG
    let output_path = "output.png";
    pixmap.save_png(output_path)?;
    
    println!("SVG成功渲染并保存为 {}", output_path);
    Ok(())
}

设计原则

Typst遵循三个核心设计原则:

  1. 通过一致性实现简单性:知识可以跨功能转移
  2. 通过可组合性实现强大功能:提供可以组合的系统
  3. 通过增量性实现性能:所有语言特性都支持增量编译

社区

Typst的主要社区在Discord服务器上,你可以在那里提问、分享作品或参与讨论。

Typst是一个强大的排版系统,结合typst-svg库可以高效处理SVG矢量图形,是轻量级的解决方案。


1 回复

Rust SVG处理库typst-svg的使用:高效解析与渲染矢量图形的轻量级解决方案

介绍

typst-svg是一个用于解析和渲染SVG(可缩放矢量图形)的轻量级Rust库。它专注于高效处理SVG文件,提供简洁的API来解析、修改和渲染矢量图形。该库特别适合需要嵌入SVG功能的应用程序,如文档生成器、图形编辑器或数据可视化工具。

主要特性

  • 轻量级且高效,没有不必要的依赖
  • 支持SVG规范的核心功能
  • 提供简洁的API进行SVG操作
  • 支持将SVG渲染为其他格式
  • 良好的错误处理机制

完整示例代码

use typst_svg::{Svg, render::{render, render_to_png}, geom::Transform};
use std::fs;

fn main() {
    // 示例1: 解析SVG文件
    let svg_data = r#"
        <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
            <circle cx="50" cy="50" r="40" fill="red" />
        </svg>
    "#;
    let svg = Svg::from_str(svg_data).expect("解析SVG失败");
    println!("SVG尺寸: {:?}", svg.view_box());

    // 示例2: 渲染SVG
    let rendered = render(&svg, 1.0); // 缩放因子1.0
    println!("渲染结果: {:?}", rendered);

    // 示例3: 修改SVG元素
    let mut svg = Svg::from_str(r#"
        <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
            <rect id="myRect" x="10" y="10" width="80" height="80" fill="green" />
        </svg>
    "#).unwrap();
    
    if let Some(rect) = svg.find_element_by_id("myRect") {
        rect.set_transform(Transform::translate(5.0, 5.0)); // 平移变换
        rect.set_attr("fill", "purple"); // 修改填充颜色
    }
    println!("修改后的SVG: {}", svg.to_string());

    // 示例4: SVG转PNG
    let png_data = render_to_png(&svg, 1.0).unwrap();
    fs::write("output.png", png_data).unwrap();

    // 示例5: 处理复杂SVG
    let complex_svg = Svg::from_str(r#"
        <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
            <defs>
                <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
                    <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
                    <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
                </linearGradient>
            </defs>
            <rect x="50" y="50" width="100" height="100" fill="url(#grad1)" />
        </svg>
    "#).unwrap();
    println!("复杂SVG元素: {:?}", complex_svg.elements());

    // 示例6: 错误处理
    match Svg::from_str("<svg>无效SVG</svg>") {
        Ok(svg) => println!("SVG解析成功"),
        Err(e) => eprintln!("SVG解析失败: {}", e),
    }
}

性能提示

  1. 对于重复使用的SVG,考虑解析一次后缓存Svg实例
  2. 使用render_with_scale时选择合适的缩放因子以避免不必要的计算
  3. 对于大型SVG文件,考虑只加载需要的部分

总结

typst-svg是一个功能强大但保持简洁的SVG处理库,非常适合需要嵌入SVG功能的Rust应用程序。它的轻量级特性使其成为许多项目的理想选择。通过上述示例,您可以快速了解如何使用该库进行SVG的解析、渲染、修改和格式转换等操作。

回到顶部