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数据结构管理与操作库,提供了多种优化的数据结构实现,特别适合需要高性能数据处理的场景。
主要功能
- 高性能集合类型
- 内存优化数据结构
- 并发安全操作
- 特殊领域数据结构
安装方法
在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);
}
}
性能建议
- 对于小型数据集,标准库数据结构可能更合适
- 在数据量超过1000元素时,fdsm的优势开始显现
- 多线程环境下优先使用fdsm提供的并发数据结构
注意事项
- API可能与标准库有所不同,请查阅文档
- 某些数据结构有额外的内存开销
- 不是所有场景都需要使用fdsm,评估后再决定