gdritter repos delve / 3eb313b
Rustdocs on the Markup helper functions Getty Ritter 6 years ago
2 changed file(s) with 95 addition(s) and 27 deletion(s). Collapse all Expand all
66 extern crate rsvg;
77
88 mod markup;
9
10 use markup::Weight;
911
1012 use std::{fs,io};
1113 use rsvg::HandleExt;
162164 Monster { ref hp, ref melee, ref ranged, ref arcane, ref defense, .. } => {
163165 buf.push(&format!("{} (Beast ", card.name));
164166
165 buf.markup().size(8).weight("heavy").push("HP");
167 buf.markup().size(8).weight(Weight::Heavy).push("HP");
166168 buf.push(&format!("{}", hp));
167169
168170 if let &Some(ref m) = melee {
169171 buf.space();
170 buf.markup().size(8).weight("heavy").push("M");
172 buf.markup().size(8).weight(Weight::Heavy).push("M");
171173 buf.push(m);
172174 }
173175
174176 if let &Some(ref m) = ranged {
175177 buf.space();
176 buf.markup().size(8).weight("heavy").push("R");
178 buf.markup().size(8).weight(Weight::Heavy).push("R");
177179 buf.push(m);
178180 }
179181
180182 if let &Some(ref m) = arcane {
181183 buf.space();
182 buf.markup().size(8).weight("heavy").push("A");
184 buf.markup().size(8).weight(Weight::Heavy).push("A");
183185 buf.push(m);
184186 }
185187
186188 if let &Some(ref m) = defense {
187189 buf.space();
188 buf.markup().size(8).weight("heavy").push("D");
190 buf.markup().size(8).weight(Weight::Heavy).push("D");
189191 buf.push(m);
190192 }
191193 buf.push(")");
194196 buf.push(&format!("{} ({:?})", card.name, kind)),
195197 };
196198
197 buf.show_with_font(&ctx, markup::title_font(), None)?;
199 buf.show_with_font(
200 &ctx,
201 markup::Font::new("Fira Sans").size(12).weight(Weight::Bold),
202 None,
203 )?;
198204
199205 ctx.move_to(115.0, 26.0);
200206 let mut buf = markup::MarkupBuffer::new();
201207
202208 match card.card_type {
203209 Weapon { ability, effect, .. } => {
204 buf.markup().weight("bold").push(&format!("{}: ", ability));
210 buf.markup().weight(Weight::Bold).push(&format!("{}: ", ability));
205211 buf.push(effect);
206212 },
207213 Monster { action, effect, .. } => {
208 buf.markup().weight("bold").push(&format!("{}: ", action));
214 buf.markup().weight(Weight::Bold).push(&format!("{}: ", action));
209215 buf.push(effect);
210216 },
211217 Generic { effect, .. } => {
213219 },
214220 };
215221
216 buf.show_with_font(&ctx, markup::body_font(), Some(390 - 115))?;
222 buf.show_with_font(
223 &ctx,
224 markup::Font::new("Fira Sans").size(10),
225 Some(390 - 115)
226 )?;
217227
218228 let icon = rsvg::Handle::new_from_file(&card.icon)
219229 .map_err(|_| format_err!("Error loading image: {}", card.icon))?;
44 use failure;
55
66 use pango::LayoutExt;
7 pub use pango::Weight;
78
9 /// A `Font` is a more convenient, less imperative abstraction over
10 /// the Pango `FontDescription` type
11 pub struct Font {
12 f: pango::FontDescription,
13 }
14
15 impl Font {
16 /// Create a new `Font` from a textual description of the font
17 pub fn new(s: &str) -> Font {
18 Font { f: pango::FontDescription::from_string(s) }
19 }
20
21 /// Set the font size in points
22 pub fn size(mut self, s: i32) -> Font {
23 self.f.set_size(s * pango::SCALE);
24 self
25 }
26
27 /// Set the font weight
28 pub fn weight(mut self, w: pango::Weight) -> Font {
29 self.f.set_weight(w);
30 self
31 }
32
33 /// Get the underlying pango `FontDescription` value
34 pub fn get(self) -> pango::FontDescription {
35 self.f
36 }
37 }
38
39 /// A `MarkupBuffer` is an abstraction that allows a high-level
40 /// mostly-correct-by-construction (in theory, anyway) approach to
41 /// adding Pango-level formatting
842 pub struct MarkupBuffer {
943 buf: String,
1044 }
1145
12 pub fn title_font() -> pango::FontDescription {
13 let mut f = pango::FontDescription::from_string("Fira Sans 12");
14 f.set_weight(pango::Weight::Bold);
15 f
16 }
17
18 pub fn body_font() -> pango::FontDescription {
19 pango::FontDescription::from_string("Fira Sans 10")
20 }
21
2246 impl MarkupBuffer {
47 /// Create a new empty `MarkupBuffer`
2348 pub fn new() -> MarkupBuffer {
2449 MarkupBuffer { buf: String::new() }
2550 }
2651
52 /// Create a view on the `MarkupBuffer` that permits markup of the
53 /// added strings
2754 pub fn markup<'a>(&'a mut self) -> Markup<'a> {
2855 Markup {
2956 view: self,
3158 }
3259 }
3360
61 /// Add a string fragment to the markup buffer
3462 pub fn push(&mut self, s: &str) {
3563 self.buf.push_str(s);
3664 }
3765
66 /// Add a single space to the buffer
3867 pub fn space(&mut self) {
3968 self.buf.push_str(" ");
4069 }
4170
42 pub fn get(self) -> String {
71 /// Get the underlying string value of the buffer
72 fn get(self) -> String {
4373 self.buf
4474 }
4575
76 /// Draw the buffer to the underlying Cairo surface, with an
77 /// optional width for layout purposes
4678 pub fn show_with_font(
4779 self,
4880 ctx: &cairo::Context,
49 font: pango::FontDescription,
81 font: Font,
5082 width: Option<i32>,
5183 ) -> Result<(), failure::Error> {
5284 let layout = pangocairo::functions::create_layout(ctx)
5385 .ok_or(format_err!("Unable to create Pango layout"))?;
54 layout.set_font_description(Some(&font));
86 layout.set_font_description(Some(&font.get()));
5587 if let Some(w) = width {
5688 layout.set_width(w * pango::SCALE);
5789 }
6597 }
6698
6799 enum Frag {
68 Weight(String),
100 Weight(pango::Weight),
69101 Size(u8),
70102 }
71103
104 /// A `Markup` value is a view into a `MarkupBuffer` that permits
105 /// extra markup to be applied transparently.
72106 pub struct Markup<'a> {
73107 view: &'a mut MarkupBuffer,
74108 frags: Vec<Frag>,
75109 }
76110
77111 impl<'a> Markup<'a> {
78 pub fn weight(self, s: &str) -> Markup<'a> {
112 /// Give this view a different weight than usual
113 pub fn weight(self, w: pango::Weight) -> Markup<'a> {
79114 let Markup { view, mut frags } = self;
80 frags.push(Frag::Weight(s.to_owned()));
115 frags.push(Frag::Weight(w));
81116 Markup { view, frags }
82117 }
83118
119 /// Set the font size in points for the view
84120 pub fn size(self, s: u8) -> Markup<'a> {
85121 let Markup { view, mut frags } = self;
86122 frags.push(Frag::Size(s));
87123 Markup { view, frags }
88124 }
89125
126 /// Add a string with the extra markup supplied
90127 pub fn push(self, s: &str) {
91128 self.view.push("<span ");
92129 for f in self.frags.iter() {
93130 match f {
94131 &Frag::Size(s) =>
95132 self.view.push(&format!("font='{}' ", s)),
96 &Frag::Weight(ref s) =>
97 self.view.push(&format!("font_weight='{}' ", s)),
133 &Frag::Weight(s) =>
134 self.view.push(&format!(
135 "font_weight='{}' ",
136 weight_to_string(s),
137 )),
98138 }
99139 }
100140 self.view.push(">");
102142 self.view.push("</span>");
103143 }
104144 }
145
146 fn weight_to_string(w: Weight) -> &'static str {
147 match w {
148 Weight::Thin => "thin",
149 Weight::Ultralight => "ultralight",
150 Weight::Light => "light",
151 Weight::Semilight => "semilight",
152 Weight::Book => "book",
153 Weight::Normal => "normal",
154 Weight::Medium => "medium",
155 Weight::Semibold => "semibold",
156 Weight::Bold => "bold",
157 Weight::Ultrabold => "ultrabold",
158 Weight::Heavy => "heavy",
159 Weight::Ultraheavy => "ultraheavy",
160 _ => panic!("Unknown weight: {:?}", w),
161 }
162 }