Fix inline nodes and decorations

Also Code Review 👯‍♂️
This commit is contained in:
Martin Haug 2022-06-01 11:43:03 +02:00
parent 4e3036afcb
commit 755d468198
7 changed files with 34 additions and 30 deletions

View File

@ -90,6 +90,7 @@ pub fn decorate(
deco: &Decoration,
fonts: &FontStore,
text: &Text,
shift: Length,
pos: Point,
width: Length,
) {
@ -102,7 +103,7 @@ pub fn decorate(
};
let evade = deco.evade && deco.line != STRIKETHROUGH;
let offset = deco.offset.unwrap_or(-metrics.position.at(text.size));
let offset = deco.offset.unwrap_or(-metrics.position.at(text.size)) - shift;
let stroke = deco.stroke.unwrap_or(Stroke {
paint: text.fill,
thickness: metrics.thickness.at(text.size),

View File

@ -555,10 +555,7 @@ fn prepare<'a>(
let shift = styles.get(TextNode::BASELINE);
if !shift.is_zero() {
Arc::make_mut(&mut frame).baseline = Some(
frame.baseline.unwrap_or(frame.size.y)
- styles.get(TextNode::BASELINE),
);
Arc::make_mut(&mut frame).translate(Point::with_y(shift));
}
items.push(Item::Frame(frame));

View File

@ -86,12 +86,17 @@ impl<'a> ShapedText<'a> {
let mut frame = Frame::new(size);
frame.baseline = Some(top);
let shift = self.styles.get(TextNode::BASELINE);
let lang = self.styles.get(TextNode::LANG);
let decos = self.styles.get(TextNode::DECO);
let fill = self.styles.get(TextNode::FILL);
let link = self.styles.get(TextNode::LINK);
for ((face_id, y_offset), group) in
self.glyphs.as_ref().group_by_key(|g| (g.face_id, g.y_offset))
{
let pos = Point::new(offset, top + y_offset.at(self.size));
let pos = Point::new(offset, top + shift + y_offset.at(self.size));
let fill = self.styles.get(TextNode::FILL);
let glyphs = group
.iter()
.map(|glyph| Glyph {
@ -111,7 +116,7 @@ impl<'a> ShapedText<'a> {
let text = Text {
face_id,
size: self.size,
lang: self.styles.get(TextNode::LANG),
lang,
fill,
glyphs,
};
@ -119,8 +124,8 @@ impl<'a> ShapedText<'a> {
let width = text.width();
// Apply line decorations.
for deco in self.styles.get(TextNode::DECO) {
decorate(&mut frame, &deco, fonts, &text, pos, width);
for deco in &decos {
decorate(&mut frame, &deco, fonts, &text, shift, pos, width);
}
frame.insert(text_layer, pos, Element::Text(text));
@ -128,8 +133,8 @@ impl<'a> ShapedText<'a> {
}
// Apply link if it exists.
if let Some(url) = self.styles.get(TextNode::LINK) {
frame.link(url.clone());
if let Some(dest) = link {
frame.link(dest.clone());
}
frame
@ -408,8 +413,6 @@ fn shape_segment<'a>(
let cluster = info.cluster as usize;
if info.glyph_id != 0 {
let baseline_shift = ctx.styles.get(TextNode::BASELINE);
// Add the glyph to the shaped output.
// TODO: Don't ignore y_advance.
ctx.glyphs.push(ShapedGlyph {
@ -417,8 +420,7 @@ fn shape_segment<'a>(
glyph_id: info.glyph_id as u16,
x_advance: face.to_em(pos[i].x_advance),
x_offset: face.to_em(pos[i].x_offset),
y_offset: face.to_em(pos[i].y_offset)
+ Em::from_length(baseline_shift, ctx.size),
y_offset: face.to_em(pos[i].y_offset),
cluster: base + cluster,
safe_to_break: !info.unsafe_to_break(),
c: text[cluster ..].chars().next().unwrap(),

View File

@ -17,7 +17,7 @@ pub type SuperNode = ShiftNode<SUPERSCRIPT>;
/// Shift the text into subscript.
pub type SubNode = ShiftNode<SUBSCRIPT>;
#[node(showable)]
#[node]
impl<const S: ScriptKind> ShiftNode<S> {
/// Whether to prefer the dedicated sub- and superscript characters of the font.
pub const TYPOGRAPHIC: bool = true;
@ -33,8 +33,8 @@ impl<const S: ScriptKind> ShiftNode<S> {
}
impl<const S: ScriptKind> Show for ShiftNode<S> {
fn unguard(&self, sel: Selector) -> ShowNode {
Self(self.0.unguard(sel)).pack()
fn unguard(&self, _: Selector) -> ShowNode {
Self(self.0.clone()).pack()
}
fn encode(&self, _: StyleChain) -> Dict {
@ -43,9 +43,9 @@ impl<const S: ScriptKind> Show for ShiftNode<S> {
fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
let mut transformed = None;
if styles.get(ShiftNode::<S>::TYPOGRAPHIC) {
if styles.get(Self::TYPOGRAPHIC) {
if let Some(text) = search_text(&self.0, S) {
if check_str_in_family(&mut ctx.fonts, &text, styles) {
if is_shapable(&mut ctx.fonts, &text, styles) {
transformed = Some(Content::Text(text));
}
}
@ -53,8 +53,8 @@ impl<const S: ScriptKind> Show for ShiftNode<S> {
Ok(transformed.unwrap_or_else(|| {
let mut map = StyleMap::new();
map.set(TextNode::BASELINE, styles.get(ShiftNode::<S>::BASELINE));
map.set(TextNode::SIZE, styles.get(ShiftNode::<S>::SIZE));
map.set(TextNode::BASELINE, styles.get(Self::BASELINE));
map.set(TextNode::SIZE, styles.get(Self::SIZE));
self.0.clone().styled_with_map(map)
}))
}
@ -73,9 +73,8 @@ fn search_text(content: &Content, mode: ScriptKind) -> Option<EcoString> {
}
None
}
Content::Space => Some(EcoString::from(" ")),
Content::Space => Some(' '.into()),
Content::Empty => Some(EcoString::new()),
Content::Styled(arc) => search_text(&arc.0, mode),
Content::Sequence(seq) => {
let mut full = EcoString::new();
for item in seq.iter() {
@ -92,11 +91,10 @@ fn search_text(content: &Content, mode: ScriptKind) -> Option<EcoString> {
/// Checks whether the first retrievable family contains all code points of the
/// given string.
fn check_str_in_family(fonts: &mut FontStore, text: &str, styles: StyleChain) -> bool {
fn is_shapable(fonts: &mut FontStore, text: &str, styles: StyleChain) -> bool {
for family in styles.get(TextNode::FAMILY).iter() {
if let Some(face_id) = fonts.select(family.as_str(), variant(styles)) {
let face = fonts.get(face_id);
let ttf = face.ttf();
let ttf = fonts.get(face_id).ttf();
return text.chars().all(|c| ttf.glyph_index(c).is_some());
}
}
@ -110,8 +108,7 @@ fn convert_script(text: &str, mode: ScriptKind) -> Option<EcoString> {
let mut result = EcoString::with_capacity(text.len());
let converter = match mode {
SUPERSCRIPT => to_superscript_codepoint,
SUBSCRIPT => to_subscript_codepoint,
_ => panic!("unknown script kind"),
SUBSCRIPT | _ => to_subscript_codepoint,
};
for c in text.chars() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@ -10,3 +10,10 @@
---
#set super(typographic: false, baseline: -0.25em, size: 0.7em)
n#super[1], n#sub[2], ... n#super[N]
---
#set underline(stroke: 0.5pt, offset: 0.15em)
#underline[The claim#super[\[4\]]] has been disputed. \
The claim#super[#underline[\[4\]]] has been disputed. \
It really has been#super(box(text(baseline: 0pt, underline[\[4\]]))) \