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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
use fontdock::FaceId;
use ttf_parser::GlyphId;
use crate::color::Color;
use crate::env::ResourceId;
use crate::geom::{Length, Path, Point, Size};
/// A finished layout with elements at fixed positions.
#[derive(Debug, Clone, PartialEq)]
pub struct Frame {
/// The size of the frame.
pub size: Size,
/// The elements composing this layout.
pub elements: Vec<(Point, Element)>,
}
impl Frame {
/// Create a new, empty frame.
pub fn new(size: Size) -> Self {
Self { size, elements: vec![] }
}
/// Add an element at a position.
pub fn push(&mut self, pos: Point, element: Element) {
self.elements.push((pos, element));
}
/// Add all elements of another frame, placing them relative to the given
/// position.
pub fn push_frame(&mut self, pos: Point, subframe: Self) {
for (subpos, element) in subframe.elements {
self.push(pos + subpos, element);
}
}
}
/// The building block frames are composed of.
#[derive(Debug, Clone, PartialEq)]
pub enum Element {
/// Shaped text.
Text(ShapedText),
/// A geometric shape.
Geometry(Geometry),
/// A raster image.
Image(Image),
}
/// A shaped run of text.
#[derive(Debug, Clone, PartialEq)]
pub struct ShapedText {
/// The font face the text was shaped with.
pub face: FaceId,
/// The font size.
pub size: Length,
/// The width.
pub width: Length,
/// The extent to the top.
pub top: Length,
/// The extent to the bottom.
pub bottom: Length,
/// The glyph fill color / texture.
pub color: Fill,
/// The shaped glyphs.
pub glyphs: Vec<GlyphId>,
/// The horizontal offsets of the glyphs. This is indexed parallel to
/// `glyphs`. Vertical offsets are not yet supported.
pub offsets: Vec<Length>,
}
impl ShapedText {
/// Create a new shape run with `width` zero and empty `glyphs` and `offsets`.
pub fn new(
face: FaceId,
size: Length,
top: Length,
bottom: Length,
color: Fill,
) -> Self {
Self {
face,
size,
width: Length::ZERO,
top,
bottom,
glyphs: vec![],
offsets: vec![],
color,
}
}
/// Encode the glyph ids into a big-endian byte buffer.
pub fn encode_glyphs_be(&self) -> Vec<u8> {
let mut bytes = Vec::with_capacity(2 * self.glyphs.len());
for &GlyphId(g) in &self.glyphs {
bytes.push((g >> 8) as u8);
bytes.push((g & 0xff) as u8);
}
bytes
}
}
/// A shape with some kind of fill.
#[derive(Debug, Clone, PartialEq)]
pub struct Geometry {
/// The shape to draw.
pub shape: Shape,
/// How the shape looks on the inside.
//
// TODO: This could be made into a Vec<Fill> or something such that
// the user can compose multiple fills with alpha values less
// than one to achieve cool effects.
pub fill: Fill,
}
/// Some shape.
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
/// A rectangle with its origin in the topleft corner.
Rect(Size),
/// An ellipse with its origin in the center.
Ellipse(Size),
/// A bezier path.
Path(Path),
}
/// The kind of graphic fill to be applied to a [`Shape`].
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Fill {
/// The fill is a color.
Color(Color),
/// The fill is an image.
Image(Image),
}
/// An image element.
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Image {
/// The image resource.
pub res: ResourceId,
/// The size of the image in the document.
pub size: Size,
}
|