Rust插件库fdsm的使用,fdsm提供高效的数据结构管理与操作功能

Rust插件库fdsm的使用,fdsm提供高效的数据结构管理与操作功能

fdsm是一个纯Rust实现的多通道有符号距离场生成库,主要遵循Victor Chlumský的硕士论文实现。虽然它不是C++ msdfgen库的直接翻译,但在部分代码上参考了该库的实现。

特性

  • visualize: 提供可视化辅助功能
  • ttf-parser特性已移至单独的fdsm-ttf-parser crate

使用方法

以下是内容中提供的示例代码:

use fdsm::bezier::scanline::FillRule;
use fdsm::generate::generate_msdf;
use fdsm::render::{correct_sign_msdf, render_msdf};
use fdsm::shape::Shape;
# use fdsm::shape::Contour;
use fdsm::transform::Transform;
use image::{GrayImage, RgbImage};
use nalgebra::{Affine2, Similarity2, Vector2};

// 首先获取一个[`Shape`]。可以通过程序生成或从字体加载获得
# #[cfg(false)] {
use ttf_parser::Face;
let face = Face::parse(notosans::REGULAR_TTF, 0).unwrap();
let glyph_id = face.glyph_index('A').unwrap();
let mut shape = fdsm_ttf_parser::load_shape_from_face(&face, glyph_id);
let bbox = face.glyph_bounding_box(glyph_id).unwrap();
# manipulate_shape(shape, bbox);
# }

# fn manipulate_shape(mut shape: Shape<Contour>, bbox: ttf_parser::Rect) {
// 准备变换矩阵并计算生成的有符号距离场的尺寸
const RANGE: f64 = 4.0;
const SHRINKAGE: f64 = 16.0;
let transformation = nalgebra::convert::<_, Affine2<f64>>(Similarity2::new(
    Vector2::new(
        RANGE - bbox.x_min as f64 / SHRINKAGE,
        RANGE - bbox.y_min as f64 / SHRINKAGE,
    ),
    0.0,
    1.0 / SHRINKAGE,
));
let width =
    ((bbox.x_max as f64 - bbox.x_min as f64) / SHRINKAGE + 2.0 * RANGE).ceil() as u32;
let height =
    ((bbox.y_max as f64 - bbox.y_min as f64) / SHRINKAGE + 2.0 * RANGE).ceil() as u32;

// 预变换形状
shape.transform(&transformation);

// 为形状的边缘着色并准备计算
let colored_shape = Shape::edge_coloring_simple(shape, 0.03, 69441337420);
let prepared_colored_shape = colored_shape.prepare();

// 设置结果图像并生成距离场
let mut msdf = RgbImage::new(width, height);
generate_msdf(&prepared_colored_shape, RANGE, &mut msdf);
correct_sign_msdf(&mut msdf, &prepared_colored_shape, FillRule::Nonzero);

// 预览距离场作为测试
let mut preview = GrayImage::new(msdf.width() * 10, msdf.height() * 10);
render_msdf(&msdf, &mut preview, RANGE);
# }

完整示例代码

use fdsm::bezier::scanline::FillRule;
use fdsm::generate::generate_msdf;
use fdsm::render::{correct_sign_msdf, render_msdf};
use fdsm::shape::{Contour, Shape};
use fdsm::transform::Transform;
use image::{GrayImage, RgbImage};
use nalgebra::{Affine2, Similarity2, Vector2};

fn main() {
    // 创建一个简单的矩形形状
    let mut shape = Shape::new();
    let mut contour = Contour::new();
    
    // 添加矩形的四个顶点
    contour.add_point(0.0, 0.0);
    contour.add_point(100.0, 0.0);
    contour.add_point(100.0, 50.0);
    contour.add_point(0.0, 50.0);
    
    shape.add_contour(contour);
    
    // 设置参数
    const RANGE: f64 = 4.0;
    const SHRINKAGE: f64 = 1.0;
    
    // 创建变换矩阵
    let transformation = Affine2::identity();
    
    // 计算输出图像尺寸
    let width = (100.0 / SHRINKAGE + 2.0 * RANGE).ceil() as u32;
    let height = (50.0 / SHRINKAGE + 2.0 * RANGE).ceil() as u32;
    
    // 应用变换
    shape.transform(&transformation);
    
    // 边缘着色和准备
    let colored_shape = Shape::edge_coloring_simple(shape, 0.03, 12345);
    let prepared_colored_shape = colored_shape.prepare();
    
    // 生成MSDF
    let mut msdf = RgbImage::new(width, height);
    generate_msdf(&prepared_colored_shape, RANGE, &mut msdf);
    correct_sign_msdf(&mut msdf, &prepared_colored_shape, FillRule::Nonzero);
    
    // 渲染预览
    let mut preview = GrayImage::new(msdf.width() * 10, msdf.height * 10);
    render_msdf(&msdf, &mut preview, RANGE);
    
    // 保存结果
    msdf.save("output_msdf.png").unwrap();
    preview.save("output_preview.png").unwrap();
}

路线图

当前fdsm已具备生成MSDF的基本功能,并能在Noto Sans字体中正确生成A到Z字母的距离场。但仍缺少部分msdfgen的功能:

  • [x] 错误校正
  • [ ] 错误估计
  • [x] 符号校正
  • [ ] 形状简化
  • [ ] 替代边缘着色算法
  • [x] 与msdfgen的基准测试

安装

在项目目录中运行以下Cargo命令:

cargo add fdsm

或在Cargo.toml中添加:

fdsm = "0.7.0"

1 回复

Rust插件库fdsm使用指南

概述

fdsm是一个高效的Rust数据结构管理与操作库,提供了多种优化的数据结构实现,特别适合需要高性能数据处理的场景。

主要功能

  1. 高性能集合类型
  2. 内存优化数据结构
  3. 并发安全操作
  4. 特殊领域数据结构

安装方法

在Cargo.toml中添加依赖:

[dependencies]
fdsm = "0.3.0"  # 请使用最新版本

基本使用方法

1. 使用高效HashMap

use fdsm::FastHashMap;

let mut map = FastHashMap::new();
map.insert("key1", 42);
map.insert("key2", 13);

if let Some(value) = map.get("key1") {
    println!("Found value: {}", value);
}

2. 使用优化的Vec替代品

use fdsm::FastVec;

let mut vec = FastVec::with_capacity(100);
vec.push(10);
vec.push(20);

for item in vec.iter() {
    println!("Item: {}", item);
}

3. 并发安全数据结构

use fdsm::ConcurrentQueue;
use std::thread;

let queue = ConcurrentQueue::new();

// 生产者线程
let producer = thread::spawn({
    let queue = queue.clone();
    move || {
        for i in 0..10 {
            queue.push(i);
        }
    }
});

// 消费者线程
let consumer = thread::spawn({
    let queue = queue.clone();
    move || {
        while let Some(item) = queue.pop() {
            println!("Consumed: {}", item);
        }
    }
});

producer.join().unwrap();
consumer.join().unwrap();

高级特性

1. 内存池技术

use fdsm::MemoryPool;

let pool = MemoryPool::<String>::new();

let s1 = pool.alloc("Hello".to_string());
let s2 = pool.alloc("World".to_string());

// 使用后可以归还到内存池
pool.free(s1);
pool.free(s2);

2. 领域特定数据结构

use fdsm::TimeSeries;

let mut series = TimeSeries::new();
series.insert(1625097600, 42.0);  // 时间戳, 值
series.insert(1625184000, 43.5);

if let Some(value) = series.query(1625097600) {
    println!("Value at timestamp: {}", value);
}

完整示例Demo

下面是一个综合使用fdsm库的完整示例:

use fdsm::{FastHashMap, FastVec, ConcurrentQueue, MemoryPool, TimeSeries};
use std::thread;

fn main() {
    // 1. FastHashMap示例
    println!("=== FastHashMap示例 ===");
    let mut scores = FastHashMap::new();
    scores.insert("Alice", 100);
    scores.insert("Bob", 85);
    scores.insert("Charlie", 92);
    
    if let Some(score) = scores.get("Alice") {
        println!("Alice的分数: {}", score);
    }

    // 2. FastVec示例
    println!("\n=== FastVec示例 ===");
    let mut numbers = FastVec::with_capacity(10);
    for i in 1..=5 {
        numbers.push(i * 10);
    }
    
    println!("所有数字:");
    for num in numbers.iter() {
        println!("{}", num);
    }

    // 3. ConcurrentQueue多线程示例
    println!("\n=== ConcurrentQueue多线程示例 ===");
    let queue = ConcurrentQueue::new();
    
    let producer = thread::spawn({
        let queue = queue.clone();
        move || {
            for i in 1..=5 {
                queue.push(i);
                println!("生产者: 发送 {}", i);
            }
        }
    });
    
    let consumer = thread::spawn({
        let queue = queue.clone();
        move || {
            for _ in 1..=5 {
                if let Some(item) = queue.pop() {
                    println!("消费者: 接收 {}", item);
                }
            }
        }
    });
    
    producer.join().unwrap();
    consumer.join().unwrap();

    // 4. MemoryPool示例
    println!("\n=== MemoryPool示例 ===");
    let pool = MemoryPool::<String>::new();
    let s1 = pool.alloc("第一个字符串".to_string());
    let s2 = pool.alloc("第二个字符串".to_string());
    
    println!("从内存池分配: {}, {}", s1, s2);
    pool.free(s1);
    pool.free(s2);

    // 5. TimeSeries示例
    println!("\n=== TimeSeries示例 ===");
    let mut sensor_data = TimeSeries::new();
    sensor_data.insert(1630000000, 25.3);
    sensor_data.insert(1630003600, 26.1);
    sensor_data.insert(1630007200, 24.8);
    
    if let Some(temp) = sensor_data.query(1630003600) {
        println!("在时间戳1630003600的温度: {}", temp);
    }
}

性能建议

  1. 对于小型数据集,标准库数据结构可能更合适
  2. 在数据量超过1000元素时,fdsm的优势开始显现
  3. 多线程环境下优先使用fdsm提供的并发数据结构

注意事项

  1. API可能与标准库有所不同,请查阅文档
  2. 某些数据结构有额外的内存开销
  3. 不是所有场景都需要使用fdsm,评估后再决定
回到顶部