# 背景
目前字体生成服务是由后端生成,但是之前的图片还有用户定制图已经切换为使用 rust
开发的图像快照服务,快照服务依赖于 rust-skia (opens new window),最近想要支持 文字段落生成,最好是可以自动排版,所以看到了 ParagraphBuilder
这个api,但是找文档没有发现关于这个api的任何线索 文档地址 (opens new window),话不多说,上代码 😄
# ParagraphBuilder 例子
因为画文字或者图案也是跟前端一样基于 Canvas
来实现的,所以我们基于 SkCanvas
封装了 Canvas
库来在项目中使用。
在同一个项目使用多个需要自己实现的库都是要基于 rust
的 workspace
哈哈哈哈哈。
可以在 src
同级目录中 新建 examples
文件夹,然后新建 paragraph.rs
文件,通过 cargo run --example 文件名
来先熟悉一下 对应库的 使用。
- 先来个 examples
use std::fs::{ File, read };
use std::io::Write;
use canvas::{
Canvas, Color, Point, textlayout, EncodedImageFormat, FontMgr,
};
fn main() {
...
let mut paragraph_builder = textlayout::ParagraphBuilder::new(¶graph_style, font_collection);
paragraph_builder.push_style(&text_style);
paragraph_builder.add_text("我是测试");
// 画到画布上去
let mut paragraph = paragraph_builder.build();
paragraph.layout(200.0);
ctx.with_canvas(|can| {
paragraph.paint(can, Point::new(0.0, 0.0));
can.save();
});
...
}
其中关键方法是通过查看源码才知道的 哈哈哈哈哈
text_style
: 文字样式let mut text_style = textlayout::TextStyle::new(); text_style .set_color(Color::RED) .set_font_size(20.6) .set_font_families(&["HYMiaoHunTiW"]) // set_font_families 首先要确保 font_collection 有这个字体,否则设置不成功 .set_letter_spacing(100.2); // .set_word_spacing(1000000000.0); 这个设置不起作用
paragraph_style
: 段落样式let mut paragraph_style = textlayout::ParagraphStyle::new(); paragraph_style.set_text_align(textlayout::TextAlign::Center); paragraph_style.set_text_direction(textlayout::TextDirection::RTL);
font_collection
: 字体集合let mut font_collection = textlayout::FontCollection::new(); let font_mgr = FontMgr::new(); font_collection.set_default_font_manager(font_mgr, None); if let Some(font_typeface_in) = font_typeface.clone() { let mut assets = textlayout::TypefaceFontProvider::new(); assets.register_typeface(font_typeface_in, Some(text_attr.font_family.to_owned())); font_collection.set_asset_font_manager(Some(assets.into())); }
# 怎么设置 横纵排列呢?
- 关键在于
paragraph.layout
这个,这个是设置 布局width
的,只有通过设置这个才能决定横纵排列
那怎么拿到 ParagraphBuilder
最终产生的段落大小呢?必须在 设置完 paragraph.layout
之后,才能通过 paragraph.longest_line()、 paragraph.height()
拿到宽高,代码如下:
...
let mut paragraph = paragraph_builder.build();
let mut layout_width = INFINITY;
if text_attr.font_layout == FontLayout::Vertical {
layout_width = text_attr.font_size;
}
paragraph.layout(layout_width);
let img_dims = (paragraph.longest_line(), paragraph.height());
let mut canvas = Canvas::new(img_dims.0 as i32, img_dims.1 as i32);
let ctx = canvas.get_context();
ctx.with_canvas(|can| {
paragraph.paint(can, Point::new(0.0, 0.0));
can.save();
});'
...
# 如果是 两列布局呢?
- 目前不知道怎么设置 两列布局,暂时想到的想法是 再次 新建
ParagraphBuilder
,然后在 画布 上绘制,相当于 按列 分割,有几列就新建几个,然后再依次绘制到画布上。。。
参考: