Fix inline nodes and decorations
Also Code Review 👯♂️
This commit is contained in:
parent
4e3036afcb
commit
755d468198
@ -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),
|
||||
|
@ -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));
|
||||
|
@ -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(),
|
||||
|
@ -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 |
@ -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\]]))) \
|
||||
|
Loading…
Reference in New Issue
Block a user