summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/exec/context.rs1
-rw-r--r--src/exec/state.rs6
-rw-r--r--src/export/pdf.rs33
-rw-r--r--src/layout/shaping.rs12
-rw-r--r--src/layout/text.rs3
-rw-r--r--src/library/font.rs7
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),