mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
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,
|
deco: &Decoration,
|
||||||
fonts: &FontStore,
|
fonts: &FontStore,
|
||||||
text: &Text,
|
text: &Text,
|
||||||
|
shift: Length,
|
||||||
pos: Point,
|
pos: Point,
|
||||||
width: Length,
|
width: Length,
|
||||||
) {
|
) {
|
||||||
@ -102,7 +103,7 @@ pub fn decorate(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let evade = deco.evade && deco.line != STRIKETHROUGH;
|
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 {
|
let stroke = deco.stroke.unwrap_or(Stroke {
|
||||||
paint: text.fill,
|
paint: text.fill,
|
||||||
thickness: metrics.thickness.at(text.size),
|
thickness: metrics.thickness.at(text.size),
|
||||||
|
@ -555,10 +555,7 @@ fn prepare<'a>(
|
|||||||
let shift = styles.get(TextNode::BASELINE);
|
let shift = styles.get(TextNode::BASELINE);
|
||||||
|
|
||||||
if !shift.is_zero() {
|
if !shift.is_zero() {
|
||||||
Arc::make_mut(&mut frame).baseline = Some(
|
Arc::make_mut(&mut frame).translate(Point::with_y(shift));
|
||||||
frame.baseline.unwrap_or(frame.size.y)
|
|
||||||
- styles.get(TextNode::BASELINE),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
items.push(Item::Frame(frame));
|
items.push(Item::Frame(frame));
|
||||||
|
@ -86,12 +86,17 @@ impl<'a> ShapedText<'a> {
|
|||||||
let mut frame = Frame::new(size);
|
let mut frame = Frame::new(size);
|
||||||
frame.baseline = Some(top);
|
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
|
for ((face_id, y_offset), group) in
|
||||||
self.glyphs.as_ref().group_by_key(|g| (g.face_id, g.y_offset))
|
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
|
let glyphs = group
|
||||||
.iter()
|
.iter()
|
||||||
.map(|glyph| Glyph {
|
.map(|glyph| Glyph {
|
||||||
@ -111,7 +116,7 @@ impl<'a> ShapedText<'a> {
|
|||||||
let text = Text {
|
let text = Text {
|
||||||
face_id,
|
face_id,
|
||||||
size: self.size,
|
size: self.size,
|
||||||
lang: self.styles.get(TextNode::LANG),
|
lang,
|
||||||
fill,
|
fill,
|
||||||
glyphs,
|
glyphs,
|
||||||
};
|
};
|
||||||
@ -119,8 +124,8 @@ impl<'a> ShapedText<'a> {
|
|||||||
let width = text.width();
|
let width = text.width();
|
||||||
|
|
||||||
// Apply line decorations.
|
// Apply line decorations.
|
||||||
for deco in self.styles.get(TextNode::DECO) {
|
for deco in &decos {
|
||||||
decorate(&mut frame, &deco, fonts, &text, pos, width);
|
decorate(&mut frame, &deco, fonts, &text, shift, pos, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.insert(text_layer, pos, Element::Text(text));
|
frame.insert(text_layer, pos, Element::Text(text));
|
||||||
@ -128,8 +133,8 @@ impl<'a> ShapedText<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply link if it exists.
|
// Apply link if it exists.
|
||||||
if let Some(url) = self.styles.get(TextNode::LINK) {
|
if let Some(dest) = link {
|
||||||
frame.link(url.clone());
|
frame.link(dest.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
frame
|
frame
|
||||||
@ -408,8 +413,6 @@ fn shape_segment<'a>(
|
|||||||
let cluster = info.cluster as usize;
|
let cluster = info.cluster as usize;
|
||||||
|
|
||||||
if info.glyph_id != 0 {
|
if info.glyph_id != 0 {
|
||||||
let baseline_shift = ctx.styles.get(TextNode::BASELINE);
|
|
||||||
|
|
||||||
// Add the glyph to the shaped output.
|
// Add the glyph to the shaped output.
|
||||||
// TODO: Don't ignore y_advance.
|
// TODO: Don't ignore y_advance.
|
||||||
ctx.glyphs.push(ShapedGlyph {
|
ctx.glyphs.push(ShapedGlyph {
|
||||||
@ -417,8 +420,7 @@ fn shape_segment<'a>(
|
|||||||
glyph_id: info.glyph_id as u16,
|
glyph_id: info.glyph_id as u16,
|
||||||
x_advance: face.to_em(pos[i].x_advance),
|
x_advance: face.to_em(pos[i].x_advance),
|
||||||
x_offset: face.to_em(pos[i].x_offset),
|
x_offset: face.to_em(pos[i].x_offset),
|
||||||
y_offset: face.to_em(pos[i].y_offset)
|
y_offset: face.to_em(pos[i].y_offset),
|
||||||
+ Em::from_length(baseline_shift, ctx.size),
|
|
||||||
cluster: base + cluster,
|
cluster: base + cluster,
|
||||||
safe_to_break: !info.unsafe_to_break(),
|
safe_to_break: !info.unsafe_to_break(),
|
||||||
c: text[cluster ..].chars().next().unwrap(),
|
c: text[cluster ..].chars().next().unwrap(),
|
||||||
|
@ -17,7 +17,7 @@ pub type SuperNode = ShiftNode<SUPERSCRIPT>;
|
|||||||
/// Shift the text into subscript.
|
/// Shift the text into subscript.
|
||||||
pub type SubNode = ShiftNode<SUBSCRIPT>;
|
pub type SubNode = ShiftNode<SUBSCRIPT>;
|
||||||
|
|
||||||
#[node(showable)]
|
#[node]
|
||||||
impl<const S: ScriptKind> ShiftNode<S> {
|
impl<const S: ScriptKind> ShiftNode<S> {
|
||||||
/// Whether to prefer the dedicated sub- and superscript characters of the font.
|
/// Whether to prefer the dedicated sub- and superscript characters of the font.
|
||||||
pub const TYPOGRAPHIC: bool = true;
|
pub const TYPOGRAPHIC: bool = true;
|
||||||
@ -33,8 +33,8 @@ impl<const S: ScriptKind> ShiftNode<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<const S: ScriptKind> Show for ShiftNode<S> {
|
impl<const S: ScriptKind> Show for ShiftNode<S> {
|
||||||
fn unguard(&self, sel: Selector) -> ShowNode {
|
fn unguard(&self, _: Selector) -> ShowNode {
|
||||||
Self(self.0.unguard(sel)).pack()
|
Self(self.0.clone()).pack()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self, _: StyleChain) -> Dict {
|
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> {
|
fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> {
|
||||||
let mut transformed = None;
|
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 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));
|
transformed = Some(Content::Text(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,8 +53,8 @@ impl<const S: ScriptKind> Show for ShiftNode<S> {
|
|||||||
|
|
||||||
Ok(transformed.unwrap_or_else(|| {
|
Ok(transformed.unwrap_or_else(|| {
|
||||||
let mut map = StyleMap::new();
|
let mut map = StyleMap::new();
|
||||||
map.set(TextNode::BASELINE, styles.get(ShiftNode::<S>::BASELINE));
|
map.set(TextNode::BASELINE, styles.get(Self::BASELINE));
|
||||||
map.set(TextNode::SIZE, styles.get(ShiftNode::<S>::SIZE));
|
map.set(TextNode::SIZE, styles.get(Self::SIZE));
|
||||||
self.0.clone().styled_with_map(map)
|
self.0.clone().styled_with_map(map)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -73,9 +73,8 @@ fn search_text(content: &Content, mode: ScriptKind) -> Option<EcoString> {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Content::Space => Some(EcoString::from(" ")),
|
Content::Space => Some(' '.into()),
|
||||||
Content::Empty => Some(EcoString::new()),
|
Content::Empty => Some(EcoString::new()),
|
||||||
Content::Styled(arc) => search_text(&arc.0, mode),
|
|
||||||
Content::Sequence(seq) => {
|
Content::Sequence(seq) => {
|
||||||
let mut full = EcoString::new();
|
let mut full = EcoString::new();
|
||||||
for item in seq.iter() {
|
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
|
/// Checks whether the first retrievable family contains all code points of the
|
||||||
/// given string.
|
/// 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() {
|
for family in styles.get(TextNode::FAMILY).iter() {
|
||||||
if let Some(face_id) = fonts.select(family.as_str(), variant(styles)) {
|
if let Some(face_id) = fonts.select(family.as_str(), variant(styles)) {
|
||||||
let face = fonts.get(face_id);
|
let ttf = fonts.get(face_id).ttf();
|
||||||
let ttf = face.ttf();
|
|
||||||
return text.chars().all(|c| ttf.glyph_index(c).is_some());
|
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 mut result = EcoString::with_capacity(text.len());
|
||||||
let converter = match mode {
|
let converter = match mode {
|
||||||
SUPERSCRIPT => to_superscript_codepoint,
|
SUPERSCRIPT => to_superscript_codepoint,
|
||||||
SUBSCRIPT => to_subscript_codepoint,
|
SUBSCRIPT | _ => to_subscript_codepoint,
|
||||||
_ => panic!("unknown script kind"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for c in text.chars() {
|
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)
|
#set super(typographic: false, baseline: -0.25em, size: 0.7em)
|
||||||
n#super[1], n#sub[2], ... n#super[N]
|
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…
x
Reference in New Issue
Block a user