diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/exec/context.rs | 1 | ||||
| -rw-r--r-- | src/exec/state.rs | 6 | ||||
| -rw-r--r-- | src/export/pdf.rs | 33 | ||||
| -rw-r--r-- | src/layout/shaping.rs | 12 | ||||
| -rw-r--r-- | src/layout/text.rs | 3 | ||||
| -rw-r--r-- | src/library/font.rs | 7 |
6 files changed, 45 insertions, 17 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs index 311619cc..761977fc 100644 --- a/src/exec/context.rs +++ b/src/exec/context.rs @@ -178,6 +178,7 @@ impl<'a> ExecContext<'a> { font_size: self.state.font.font_size(), top_edge: self.state.font.top_edge, bottom_edge: self.state.font.bottom_edge, + color: self.state.font.color, } } diff --git a/src/exec/state.rs b/src/exec/state.rs index 6775f394..f66694fd 100644 --- a/src/exec/state.rs +++ b/src/exec/state.rs @@ -2,8 +2,9 @@ use std::rc::Rc; use fontdock::{fallback, FallbackTree, FontStretch, FontStyle, FontVariant, FontWeight}; +use crate::color::{Color, RgbaColor}; use crate::geom::*; -use crate::layout::VerticalFontMetric; +use crate::layout::{Fill, VerticalFontMetric}; use crate::paper::{Paper, PaperClass, PAPER_A4}; /// The evaluation state. @@ -115,6 +116,8 @@ pub struct FontState { /// Whether the emphasis toggle is active or inactive. This determines /// whether the next `_` makes italic or non-italic. pub emph: bool, + /// The glyph fill color / texture. + pub color: Fill, } impl FontState { @@ -149,6 +152,7 @@ impl Default for FontState { scale: Linear::ONE, strong: false, emph: false, + color: Fill::Color(Color::Rgba(RgbaColor::BLACK)), } } } diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 43c58403..d8391e2d 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -133,6 +133,22 @@ impl<'a> PdfExporter<'a> { // do that, we need to remember the active face. let mut face = FaceId::MAX; let mut size = Length::ZERO; + let mut fill: Option<Fill> = None; + let mut change_color = |content: &mut Content, new_fill: Fill| { + if fill != Some(new_fill) { + match new_fill { + Fill::Color(Color::Rgba(c)) => { + content.fill_rgb( + c.r as f32 / 255.0, + c.g as f32 / 255.0, + c.b as f32 / 255.0, + ); + } + Fill::Image(_) => todo!(), + } + fill = Some(new_fill); + } + }; for (pos, element) in &page.elements { let x = pos.x.to_pt() as f32; @@ -152,17 +168,7 @@ impl<'a> PdfExporter<'a> { Element::Geometry(geometry) => { content.save_state(); - - match geometry.fill { - Fill::Color(Color::Rgba(c)) => { - content.fill_rgb( - c.r as f32 / 255.0, - c.g as f32 / 255.0, - c.b as f32 / 255.0, - ); - } - Fill::Image(_) => todo!(), - } + change_color(&mut content, geometry.fill); match &geometry.shape { Shape::Rect(r) => { @@ -179,9 +185,12 @@ impl<'a> PdfExporter<'a> { } Element::Text(shaped) => { + change_color(&mut content, shaped.color); + let mut text = content.text(); - // Check if we need to issue a font switching action. + // Then, also check if we need to + // issue a font switching action. if shaped.face != face || shaped.font_size != size { face = shaped.face; size = shaped.font_size; diff --git a/src/layout/shaping.rs b/src/layout/shaping.rs index 1b769db7..df27e287 100644 --- a/src/layout/shaping.rs +++ b/src/layout/shaping.rs @@ -11,7 +11,7 @@ use ttf_parser::{Face, GlyphId}; use crate::env::FontLoader; use crate::geom::{Dir, Length, Point, Size}; -use crate::layout::{Element, Frame}; +use crate::layout::{Element, Fill, Frame}; /// A shaped run of text. #[derive(Clone, PartialEq)] @@ -27,17 +27,20 @@ pub struct Shaped { pub offsets: Vec<Length>, /// The font size. pub font_size: Length, + /// The glyph fill color / texture. + pub color: Fill, } impl Shaped { /// Create a new shape run with empty `text`, `glyphs` and `offsets`. - pub fn new(face: FaceId, font_size: Length) -> Self { + pub fn new(face: FaceId, font_size: Length, color: Fill) -> Self { Self { text: String::new(), face, glyphs: vec![], offsets: vec![], font_size, + color: color, } } @@ -100,10 +103,11 @@ pub fn shape( font_size: Length, top_edge: VerticalFontMetric, bottom_edge: VerticalFontMetric, + color: Fill, loader: &mut FontLoader, ) -> Frame { let mut frame = Frame::new(Size::new(Length::ZERO, Length::ZERO)); - let mut shaped = Shaped::new(FaceId::MAX, font_size); + let mut shaped = Shaped::new(FaceId::MAX, font_size, color); let mut width = Length::ZERO; let mut top = Length::ZERO; let mut bottom = Length::ZERO; @@ -133,7 +137,7 @@ pub fn shape( if shaped.face != id { place(&mut frame, shaped, width, top, bottom); - shaped = Shaped::new(id, font_size); + shaped = Shaped::new(id, font_size, color); width = Length::ZERO; top = convert(f64::from(lookup_metric(face, top_edge))); bottom = convert(f64::from(lookup_metric(face, bottom_edge))); diff --git a/src/layout/text.rs b/src/layout/text.rs index 7faefa0d..7f8f97cc 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -24,6 +24,8 @@ pub struct TextNode { pub top_edge: VerticalFontMetric, /// The bottom end of the text bounding box. pub bottom_edge: VerticalFontMetric, + /// The glyph fill. + pub color: Fill, } impl Layout for TextNode { @@ -37,6 +39,7 @@ impl Layout for TextNode { self.font_size, self.top_edge, self.bottom_edge, + self.color, &mut ctx.env.fonts, ), self.aligns, diff --git a/src/library/font.rs b/src/library/font.rs index 00fd0e81..0993f7f0 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -1,3 +1,4 @@ +use crate::layout::Fill; use fontdock::{FontStretch, FontStyle, FontWeight}; use super::*; @@ -15,6 +16,7 @@ use super::*; /// - Font Stretch: `stretch`, of type `relative`, between 0.5 and 2.0. /// - Top edge of the font: `top-edge`, of type `vertical-font-metric`. /// - Bottom edge of the font: `bottom-edge`, of type `vertical-font-metric`. +/// - Fill color the glyphs: `color`, of type `color`. /// - Serif family definition: `serif`, of type `font-familiy-list`. /// - Sans-serif family definition: `sans-serif`, of type `font-familiy-list`. /// - Monospace family definition: `monospace`, of type `font-familiy-list`. @@ -62,6 +64,7 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { let stretch = args.get(ctx, "stretch"); let top_edge = args.get(ctx, "top-edge"); let bottom_edge = args.get(ctx, "bottom-edge"); + let color = args.get(ctx, "color"); let serif = args.get(ctx, "serif"); let sans_serif = args.get(ctx, "sans-serif"); let monospace = args.get(ctx, "monospace"); @@ -105,6 +108,10 @@ pub fn font(ctx: &mut EvalContext, args: &mut FuncArgs) -> Value { ctx.state.font.bottom_edge = bottom_edge; } + if let Some(color) = color { + ctx.state.font.color = Fill::Color(color); + } + for (variant, arg) in &[ (FontFamily::Serif, &serif), (FontFamily::SansSerif, &sans_serif), |
