-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathlib.rs
90 lines (77 loc) · 2.92 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::collections::HashSet;
use entry::Flow;
use pathfinder_geometry::transform2d::Transform2F;
use pdf::{backend::Backend, object::{Page, Resolve}, PdfError};
use pdf_render::{tracer::{TraceCache, Tracer, DrawItem}, Fill, render_pattern, render_page, FillMode, font::OutlineBuilder};
mod tree;
mod util;
mod text;
pub mod entry;
pub fn run<B: Backend>(file: &pdf::file::CachedFile<B>, page: &Page, resolve: &impl Resolve, transform: Transform2F) -> Result<Flow, PdfError> {
let mut cache = TraceCache::new(OutlineBuilder::default());
let mut clip_paths = vec![];
let mut tracer = Tracer::new(&mut cache, &mut clip_paths);
render_page(&mut tracer, resolve, &page, transform)?;
let bbox = tracer.view_box();
let items: Vec<DrawItem<OutlineBuilder>> = tracer.finish();
let mut patterns = HashSet::new();
for item in items.iter() {
if let DrawItem::Vector(ref v) = item {
if let Some(FillMode { color: Fill::Pattern(id), .. }) = v.fill {
patterns.insert(id);
}
if let Some((FillMode { color: Fill::Pattern(id), .. }, _)) = v.stroke {
patterns.insert(id);
}
}
}
let mut spans = vec![];
let mut lines = vec![];
let mut visit_item = |item| {
match item {
DrawItem::Text(t, _) if bbox.intersects(t.rect) => {
spans.push(t);
}
DrawItem::Vector(path) if bbox.intersects(path.outline.bounds()) => {
for contour in path.outline.contours() {
use pathfinder_content::{outline::ContourIterFlags, segment::SegmentKind};
for segment in contour.iter(ContourIterFlags::empty()) {
match segment.kind {
SegmentKind::Line => lines.push([
segment.baseline.from_x(),
segment.baseline.from_y(),
segment.baseline.to_x(),
segment.baseline.to_y()
]),
_ => {}
}
}
}
}
_ => {}
}
};
for &p in patterns.iter() {
let pattern = match resolve.get(p) {
Ok(p) => p,
Err(e) => {
log::warn!("failed to load pattern: {:?}", e);
continue;
}
};
let mut pat_tracer = Tracer::new(&mut cache, &mut clip_paths);
render_pattern(&mut pat_tracer, &*pattern, resolve)?;
let pat_items = pat_tracer.finish();
for item in pat_items {
visit_item(item);
}
}
for item in items {
visit_item(item);
}
let root = tree::build(&spans, bbox, &lines);
// dbg!(&root);
let mut flow = Flow::new();
tree::items(&mut flow, &spans, &root, bbox.min_x());
Ok(flow)
}