Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hihglighted text rasterization #69

Merged
merged 3 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ libc = "0.2.81"
tiny-skia = "0.6.1"
# FIXME: switchback after https://github.com/lunaryorn/systemd-journal-logger.rs/pull/8
systemd-journal-logger = { git = "https://github.com/l4l/systemd-journal-logger.rs.git", branch = "nix_22" }
unicode-segmentation = "1.8.0"

[profile.release]
lto = true
Expand Down
4 changes: 2 additions & 2 deletions src/draw/input_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::f32::consts;
use raqote::{DrawOptions, DrawTarget, PathBuilder, Point, SolidSource, Source};

use super::{Drawable, Space};
use crate::font::{Font, FontBackend};
use crate::font::{Font, FontBackend, FontColor};
use crate::style::{Margin, Padding};

pub struct Params {
Expand Down Expand Up @@ -79,7 +79,7 @@ impl<'a> Drawable for InputText<'a> {
self.text,
font_size,
pos,
self.params.font_color,
FontColor::Single(self.params.font_color),
&DrawOptions::new(),
);

Expand Down
52 changes: 17 additions & 35 deletions src/draw/list_view.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::marker::PhantomData;
use std::ops::Range;

use bit_vec::BitVec;
use itertools::Itertools;
use oneshot::Sender;
use raqote::{AntialiasMode, DrawOptions, DrawTarget, Image, Point, SolidSource};

use super::{Drawable, Space};
use crate::font::{Font, FontBackend};
use crate::font::{Font, FontBackend, FontColor};
use crate::style::Margin;
use unicode_segmentation::UnicodeSegmentation;

pub struct Params {
pub font: Font,
Expand Down Expand Up @@ -130,39 +130,19 @@ where
let empty = BitVec::new();
let match_ranges = item.match_mask.unwrap_or(&empty);

fn substr<'a, 'b: 'a>(x: &'b str, r: &Range<usize>) -> &'a str {
let start = x
.char_indices()
.nth(r.start)
.map(|x| x.0)
.unwrap_or_else(|| x.len());
let end = x
.char_indices()
.nth(r.end.saturating_sub(1))
.map(|l| l.0 + l.1.len_utf8())
.unwrap_or_else(|| x.len());
&x[start..end]
}

let antialias = AntialiasMode::Gray;
let draw_opts = DrawOptions {
antialias,
..DrawOptions::new()
};

if let Some(match_color) = self.params.match_color {
let font = &self.params.font;
macro_rules! draw_substr {
($range:expr, $pos:expr, $color:expr) => {{
let s = substr(item.name, $range);
let width = font.measure_text_width(&dt, font_size, s, antialias);
let color = if let Some(match_color) = self.params.match_color {
let mut special_color =
vec![color; UnicodeSegmentation::graphemes(item.name, true).count()];

font.draw(&mut dt, s, font_size, $pos, $color, &draw_opts);
Point::new($pos.x + width, $pos.y)
}};
}
let special_len = special_color.len();

let (pos, idx) = match_ranges
match_ranges
.iter()
.group_by(|x| *x)
.into_iter()
Expand All @@ -174,19 +154,21 @@ where
*start += count;
Some((group.0, range))
})
.fold((pos, 0), |(pos, _), (is_matched, range)| {
.for_each(|(is_matched, range)| {
let color = if is_matched { match_color } else { color };

(draw_substr!(&range, pos, color), range.end)
if range.start < special_len {
special_color[range.start..range.end.min(special_len)].fill(color);
}
});

let tail_str = substr(item.name, &(idx..item.name.chars().count()));
font.draw(&mut dt, tail_str, font_size, pos, color, &draw_opts);
FontColor::Multiple(special_color)
} else {
self.params
.font
.draw(&mut dt, item.name, font_size, pos, color, &draw_opts);
}
FontColor::Single(color)
};

let font = &self.params.font;
font.draw(&mut dt, item.name, font_size, pos, color, &draw_opts);
}

space
Expand Down
7 changes: 6 additions & 1 deletion src/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ mod fdue;
#[cfg(feature = "font-fontdue")]
pub type Font = fdue::Font;

pub enum FontColor {
Multiple(Vec<SolidSource>),
Single(SolidSource),
}

pub trait FontBackend: Sized {
fn default() -> Self {
const DEFAULT_FONT: &str = "DejaVu Sans Mono";
Expand All @@ -29,7 +34,7 @@ pub trait FontBackend: Sized {
text: &str,
font_size: f32,
start_pos: Point,
color: SolidSource,
color: FontColor,
opts: &DrawOptions,
);

Expand Down
11 changes: 8 additions & 3 deletions src/font/fdue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use once_cell::sync::Lazy;
use raqote::{AntialiasMode, DrawOptions, DrawTarget, Point, SolidSource};
use rust_fontconfig::{FcFontCache, FcFontPath, FcPattern, PatternMatch};

use super::{FontBackend, Result};
use super::{FontBackend, FontColor, Result};

static FONTCONFIG: Lazy<FontConfig> = Lazy::new(FontConfig::new);
const BUF_SIZE: usize = 256 * 256;
Expand Down Expand Up @@ -83,7 +83,7 @@ impl FontBackend for Font {
text: &str,
font_size: f32,
start_pos: Point,
color: SolidSource,
color: FontColor,
opts: &DrawOptions,
) {
let mut buf = FONTCONFIG.buffer.borrow_mut();
Expand All @@ -99,13 +99,18 @@ impl FontBackend for Font {

layout.append(&[&self.inner], &TextStyle::new(text, font_size, 0));

for g in layout.glyphs() {
for (n, g) in layout.glyphs().iter().enumerate() {
let (_, b) = self.inner.rasterize_config(g.key);

assert!(g.width * g.height <= BUF_SIZE);
let width = g.width as i32;
let height = g.height as i32;

let color = match color {
FontColor::Single(color) => color,
FontColor::Multiple(ref colors) => colors[n],
};

for (i, x) in b.into_iter().enumerate() {
let src = SolidSource::from_unpremultiplied_argb(
(u32::from(x) * u32::from(color.a) / 255) as u8,
Expand Down
13 changes: 10 additions & 3 deletions src/font/fontkit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use font_kit::family_name::FamilyName;
pub use font_kit::loaders::freetype::Font;
use font_kit::properties::Properties;
use font_kit::source::SystemSource;
use raqote::{AntialiasMode, DrawOptions, DrawTarget, Point, SolidSource, Source};
use raqote::{AntialiasMode, DrawOptions, DrawTarget, Point, Source};

use super::{FontBackend, Result};
use super::{FontBackend, FontColor, Result};

impl FontBackend for Font {
fn default() -> Self {
Expand All @@ -28,7 +28,7 @@ impl FontBackend for Font {
text: &str,
font_size: f32,
start_pos: Point,
color: SolidSource,
color: FontColor,
opts: &DrawOptions,
) {
let start = pathfinder_geometry::vector::vec2f(start_pos.x, start_pos.y + font_size);
Expand Down Expand Up @@ -66,6 +66,13 @@ impl FontBackend for Font {
},
);

let color = match color {
FontColor::Single(color) => color,
// Take just 1st color in vector, fontkit have a lot of problems in rasterize, so it is not a big deal
// May be delete this font?
FontColor::Multiple(ref colors) => colors[0],
};
l4l marked this conversation as resolved.
Show resolved Hide resolved

dt.draw_glyphs(
self,
font_size,
Expand Down