Add capability to synthesize italic
This commit is contained in:
parent
46d60a3723
commit
bd5f2f95e8
7 changed files with 55 additions and 7 deletions
|
|
@ -10,6 +10,7 @@ repository = "https://github.com/pop-os/cosmic-text"
|
||||||
rust-version = "1.65"
|
rust-version = "1.65"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bitflags = "2.4.1"
|
||||||
cosmic_undo_2 = { version = "0.2.0", optional = true }
|
cosmic_undo_2 = { version = "0.2.0", optional = true }
|
||||||
fontdb = { version = "0.16.0", default-features = false }
|
fontdb = { version = "0.16.0", default-features = false }
|
||||||
hashbrown = { version = "0.14.1", optional = true, default-features = false }
|
hashbrown = { version = "0.14.1", optional = true, default-features = false }
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use cosmic_text::{
|
use cosmic_text::{
|
||||||
Action, Attrs, Buffer, Color, Edit, Editor, Family, FontSystem, Metrics, Motion, Shaping,
|
Action, Attrs, Buffer, CacheKeyFlags, Color, Edit, Editor, Family, FontSystem, Metrics, Motion,
|
||||||
Style, SwashCache, Weight,
|
Shaping, Style, SwashCache, Weight,
|
||||||
};
|
};
|
||||||
use orbclient::{EventOption, Renderer, Window, WindowFlag};
|
use orbclient::{EventOption, Renderer, Window, WindowFlag};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -63,6 +63,10 @@ fn main() {
|
||||||
("Sans-Serif Normal ", attrs),
|
("Sans-Serif Normal ", attrs),
|
||||||
("Sans-Serif Bold ", attrs.weight(Weight::BOLD)),
|
("Sans-Serif Bold ", attrs.weight(Weight::BOLD)),
|
||||||
("Sans-Serif Italic ", attrs.style(Style::Italic)),
|
("Sans-Serif Italic ", attrs.style(Style::Italic)),
|
||||||
|
(
|
||||||
|
"Sans-Serif Fake Italic ",
|
||||||
|
attrs.cache_key_flags(CacheKeyFlags::FAKE_ITALIC),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"Sans-Serif Bold Italic\n",
|
"Sans-Serif Bold Italic\n",
|
||||||
attrs.weight(Weight::BOLD).style(Style::Italic),
|
attrs.weight(Weight::BOLD).style(Style::Italic),
|
||||||
|
|
|
||||||
15
src/attrs.rs
15
src/attrs.rs
|
|
@ -6,9 +6,11 @@ use alloc::{
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
use rangemap::RangeMap;
|
||||||
|
|
||||||
|
use crate::CacheKeyFlags;
|
||||||
|
|
||||||
pub use fontdb::{Family, Stretch, Style, Weight};
|
pub use fontdb::{Family, Stretch, Style, Weight};
|
||||||
use rangemap::RangeMap;
|
|
||||||
|
|
||||||
/// Text color
|
/// Text color
|
||||||
#[derive(Clone, Copy, Debug, PartialOrd, Ord, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialOrd, Ord, Eq, Hash, PartialEq)]
|
||||||
|
|
@ -109,6 +111,7 @@ pub struct Attrs<'a> {
|
||||||
pub style: Style,
|
pub style: Style,
|
||||||
pub weight: Weight,
|
pub weight: Weight,
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Attrs<'a> {
|
impl<'a> Attrs<'a> {
|
||||||
|
|
@ -123,6 +126,7 @@ impl<'a> Attrs<'a> {
|
||||||
style: Style::Normal,
|
style: Style::Normal,
|
||||||
weight: Weight::NORMAL,
|
weight: Weight::NORMAL,
|
||||||
metadata: 0,
|
metadata: 0,
|
||||||
|
cache_key_flags: CacheKeyFlags::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,6 +166,12 @@ impl<'a> Attrs<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set [`CacheKeyFlags`]
|
||||||
|
pub fn cache_key_flags(mut self, cache_key_flags: CacheKeyFlags) -> Self {
|
||||||
|
self.cache_key_flags = cache_key_flags;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if font matches
|
/// Check if font matches
|
||||||
pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
|
pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
|
||||||
//TODO: smarter way of including emoji
|
//TODO: smarter way of including emoji
|
||||||
|
|
@ -190,6 +200,7 @@ pub struct AttrsOwned {
|
||||||
pub style: Style,
|
pub style: Style,
|
||||||
pub weight: Weight,
|
pub weight: Weight,
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttrsOwned {
|
impl AttrsOwned {
|
||||||
|
|
@ -201,6 +212,7 @@ impl AttrsOwned {
|
||||||
style: attrs.style,
|
style: attrs.style,
|
||||||
weight: attrs.weight,
|
weight: attrs.weight,
|
||||||
metadata: attrs.metadata,
|
metadata: attrs.metadata,
|
||||||
|
cache_key_flags: attrs.cache_key_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,6 +224,7 @@ impl AttrsOwned {
|
||||||
style: self.style,
|
style: self.style,
|
||||||
weight: self.weight,
|
weight: self.weight,
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
|
cache_key_flags: self.cache_key_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
|
bitflags::bitflags! {
|
||||||
|
/// Flags that change rendering
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct CacheKeyFlags: u32 {
|
||||||
|
/// Skew by 14 degrees to synthesize italic
|
||||||
|
const FAKE_ITALIC = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Key for building a glyph cache
|
/// Key for building a glyph cache
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||||
pub struct CacheKey {
|
pub struct CacheKey {
|
||||||
|
|
@ -13,6 +23,8 @@ pub struct CacheKey {
|
||||||
pub x_bin: SubpixelBin,
|
pub x_bin: SubpixelBin,
|
||||||
/// Binning of fractional Y offset
|
/// Binning of fractional Y offset
|
||||||
pub y_bin: SubpixelBin,
|
pub y_bin: SubpixelBin,
|
||||||
|
/// [`CacheKeyFlags`]
|
||||||
|
pub flags: CacheKeyFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheKey {
|
impl CacheKey {
|
||||||
|
|
@ -21,6 +33,7 @@ impl CacheKey {
|
||||||
glyph_id: u16,
|
glyph_id: u16,
|
||||||
font_size: f32,
|
font_size: f32,
|
||||||
pos: (f32, f32),
|
pos: (f32, f32),
|
||||||
|
flags: CacheKeyFlags,
|
||||||
) -> (Self, i32, i32) {
|
) -> (Self, i32, i32) {
|
||||||
let (x, x_bin) = SubpixelBin::new(pos.0);
|
let (x, x_bin) = SubpixelBin::new(pos.0);
|
||||||
let (y, y_bin) = SubpixelBin::new(pos.1);
|
let (y, y_bin) = SubpixelBin::new(pos.1);
|
||||||
|
|
@ -31,6 +44,7 @@ impl CacheKey {
|
||||||
font_size_bits: font_size.to_bits(),
|
font_size_bits: font_size.to_bits(),
|
||||||
x_bin,
|
x_bin,
|
||||||
y_bin,
|
y_bin,
|
||||||
|
flags,
|
||||||
},
|
},
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use core::fmt::Display;
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::{CacheKey, Color};
|
use crate::{CacheKey, CacheKeyFlags, Color};
|
||||||
|
|
||||||
/// A laid out glyph
|
/// A laid out glyph
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -50,6 +50,8 @@ pub struct LayoutGlyph {
|
||||||
pub color_opt: Option<Color>,
|
pub color_opt: Option<Color>,
|
||||||
/// Metadata from `Attrs`
|
/// Metadata from `Attrs`
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
|
/// [`CacheKeyFlags`]
|
||||||
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -75,6 +77,7 @@ impl LayoutGlyph {
|
||||||
(self.x + x_offset) * scale + offset.0,
|
(self.x + x_offset) * scale + offset.0,
|
||||||
libm::truncf((self.y - y_offset) * scale + offset.1), // Hinting in Y axis
|
libm::truncf((self.y - y_offset) * scale + offset.1), // Hinting in Y axis
|
||||||
),
|
),
|
||||||
|
self.cache_key_flags,
|
||||||
);
|
);
|
||||||
|
|
||||||
PhysicalGlyph { cache_key, x, y }
|
PhysicalGlyph { cache_key, x, y }
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::fallback::FontFallbackIter;
|
use crate::fallback::FontFallbackIter;
|
||||||
use crate::{
|
use crate::{
|
||||||
Align, AttrsList, Color, Font, FontSystem, LayoutGlyph, LayoutLine, ShapePlanCache, Wrap,
|
Align, AttrsList, CacheKeyFlags, Color, Font, FontSystem, LayoutGlyph, LayoutLine,
|
||||||
|
ShapePlanCache, Wrap,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The shaping strategy of some text.
|
/// The shaping strategy of some text.
|
||||||
|
|
@ -148,6 +149,7 @@ fn shape_fallback(
|
||||||
//TODO: color should not be related to shaping
|
//TODO: color should not be related to shaping
|
||||||
color_opt: attrs.color_opt,
|
color_opt: attrs.color_opt,
|
||||||
metadata: attrs.metadata,
|
metadata: attrs.metadata,
|
||||||
|
cache_key_flags: attrs.cache_key_flags,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -373,6 +375,7 @@ fn shape_skip(
|
||||||
glyph_id,
|
glyph_id,
|
||||||
color_opt: attrs.color_opt,
|
color_opt: attrs.color_opt,
|
||||||
metadata: attrs.metadata,
|
metadata: attrs.metadata,
|
||||||
|
cache_key_flags: attrs.cache_key_flags,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
@ -393,6 +396,7 @@ pub struct ShapeGlyph {
|
||||||
pub glyph_id: u16,
|
pub glyph_id: u16,
|
||||||
pub color_opt: Option<Color>,
|
pub color_opt: Option<Color>,
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShapeGlyph {
|
impl ShapeGlyph {
|
||||||
|
|
@ -418,6 +422,7 @@ impl ShapeGlyph {
|
||||||
y_offset: self.y_offset,
|
y_offset: self.y_offset,
|
||||||
color_opt: self.color_opt,
|
color_opt: self.color_opt,
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
|
cache_key_flags: self.cache_key_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/swash.rs
12
src/swash.rs
|
|
@ -7,10 +7,10 @@ use swash::scale::{image::Content, ScaleContext};
|
||||||
use swash::scale::{Render, Source, StrikeWith};
|
use swash::scale::{Render, Source, StrikeWith};
|
||||||
use swash::zeno::{Format, Vector};
|
use swash::zeno::{Format, Vector};
|
||||||
|
|
||||||
use crate::{CacheKey, Color, FontSystem, HashMap};
|
use crate::{CacheKey, CacheKeyFlags, Color, FontSystem, HashMap};
|
||||||
|
|
||||||
pub use swash::scale::image::{Content as SwashContent, Image as SwashImage};
|
pub use swash::scale::image::{Content as SwashContent, Image as SwashImage};
|
||||||
pub use swash::zeno::{Command, Placement};
|
pub use swash::zeno::{Angle, Command, Placement, Transform};
|
||||||
|
|
||||||
fn swash_image(
|
fn swash_image(
|
||||||
font_system: &mut FontSystem,
|
font_system: &mut FontSystem,
|
||||||
|
|
@ -49,6 +49,14 @@ fn swash_image(
|
||||||
.format(Format::Alpha)
|
.format(Format::Alpha)
|
||||||
// Apply the fractional offset
|
// Apply the fractional offset
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
|
.transform(if cache_key.flags.contains(CacheKeyFlags::FAKE_ITALIC) {
|
||||||
|
Some(Transform::skew(
|
||||||
|
Angle::from_degrees(14.0),
|
||||||
|
Angle::from_degrees(0.0),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
// Render the image
|
// Render the image
|
||||||
.render(&mut scaler, cache_key.glyph_id)
|
.render(&mut scaler, cache_key.glyph_id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue