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

Use rustybuzz for shaping and enable by default; allow custom font aliases #199

Merged
merged 5 commits into from
Jun 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
4 changes: 1 addition & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,4 @@ jobs:
- name: test (kas-theme)
run: cargo test --manifest-path kas-theme/Cargo.toml
- name: test (kas-wgpu)
run: |
cargo test --manifest-path kas-wgpu/Cargo.toml
cargo test --manifest-path kas-wgpu/Cargo.toml --features clipboard,shaping
run: cargo test --manifest-path kas-wgpu/Cargo.toml --features clipboard
12 changes: 7 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ rustdoc-args = ["--cfg", "doc_cfg"]
# RUSTDOCFLAGS="--cfg doc_cfg" cargo +nightly doc --features=nightly,internal_doc,markdown,yaml,json --all --no-deps --open

[features]
default = ["shaping"]

# Enables usage of unstable Rust features
nightly = ["min_spec"]

Expand All @@ -34,18 +36,18 @@ min_spec = []
# This flag does not change the API, only built documentation.
internal_doc = []

# Enables text shaping via HarfBuzz
# Shaping is part of Complex Text Layout, used for ligatures and where form
# depends on position and context (especially important for Arabic).
# Enable shaping via rustybuzz
shaping = ["kas-text/shaping"]
# Force use of HarfBuzz for shaping
harfbuzz = ["kas-text/harfbuzz"]

# Enable Markdown parsing
markdown = ["kas-text/markdown"]

# Enable config read/write
#TODO(cargo): once weak-dep-features (cargo#8832) is stable, add "winit?/serde"
# and remove the serde feature requirement under dependencies.winit.
config = ["serde"]
config = ["serde", "kas-text/serde"]

# Enable support for YAML (de)serialisation
yaml = ["config", "serde_yaml"]
Expand Down Expand Up @@ -87,4 +89,4 @@ features = ["serde"]
members = ["kas-macros", "kas-theme", "kas-wgpu"]

[patch.crates-io]
kas-text = { git = "https://github.com/kas-gui/kas-text.git", rev = "df3fcc1b6a8f8644c0b799021045248bc29098c8" }
kas-text = { git = "https://github.com/kas-gui/kas-text.git", rev = "c594569d5d8a4640c2b76865114453b2701d0c35" }
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,6 @@ Currently, KAS's only drawing method is [WebGPU] which requires DirectX 11/12,
Vulkan or Metal.
In the future, there may be support for OpenGL and software rendering.

#### HarfBuzz (optional)

This is only needed if the `shaping` feature is enabled. On my system, the
following libraries are used: `libharfbuzz.so.0`, `libglib-2.0.so.0`,
`libgraphite2.so.3` and `libpcre.so.1`.

### Quick-start

Install dependencies:
Expand Down Expand Up @@ -184,8 +178,8 @@ and runs the UI.

The `kas` crate has the following feature flags:

- `shaping`: enables complex glyph forming for languages such as Arabic.
This requires that the HarfBuzz library is installed.
- `shaping` (enabled by default): enables complex glyph forming for languages such as Arabic.
Alternate: `harfbuzz` forces use of the HarfBuzz library for shaping.
- `markdown`: enables Markdown parsing for rich-text
- `config`: adds (de)serialisation support for configuration plus a few
utility types (specifying `serde` instead only implements for utility types)
Expand Down
45 changes: 45 additions & 0 deletions example-config/theme.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
font_size: 10.0
active_scheme: dark
color_schemes:
"":
background: "#FFFFFF"
frame: "#DADADA"
bg: "#FFFFFF"
bg_disabled: "#EDEDED"
bg_error: "#FFBCBC"
text: "#000000"
text_sel: "#FFFFFF"
text_sel_bg: "#6CC0E1"
label_text: "#000000"
button_text: "#FFFFFF"
nav_focus: "#F3D3AA"
button: "#7CDAFF"
button_disabled: "#BCBCBC"
button_highlighted: "#89E7FF"
button_depressed: "#6CC0E1"
checkbox: "#7CDAFF"
dark:
background: "#4d4f50"
frame: "#AAAAAA"
bg: "#595959"
bg_disabled: "#959595"
bg_error: "#FFBCBC"
text: "#FFFFFF"
text_sel: "#FFFFFF"
text_sel_bg: "#CB9559"
label_text: "#FFFFFF"
button_text: "#FFFFFF"
nav_focus: "#FFDABC"
button: "#BC5959"
button_disabled: "#DADADA"
button_highlighted: "#CB9559"
button_depressed: "#955959"
checkbox: "#BC5959"
font_aliases:
sans-serif:
mode: Prepend
list: [Calibri]
Calibri:
mode: Append
list: [Carlito]
31 changes: 31 additions & 0 deletions kas-theme/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//! Theme configuration

use crate::{ColorsLinear, ColorsSrgb, ThemeConfig};
use kas::text::fonts::{fonts, AddMode};
use kas::TkAction;
use std::collections::BTreeMap;

Expand All @@ -16,16 +17,23 @@ pub struct Config {
#[cfg_attr(feature = "config", serde(skip))]
dirty: bool,

/// Standard font size, in units of points-per-Em
#[cfg_attr(feature = "config", serde(default = "defaults::font_size"))]
font_size: f32,

/// The colour scheme to use
#[cfg_attr(feature = "config", serde(default))]
active_scheme: String,

/// All colour schemes
/// TODO: possibly we should not save default schemes and merge when
/// loading (perhaps via a `PartialConfig` type).
#[cfg_attr(feature = "config", serde(default = "defaults::color_schemes",))]
color_schemes: BTreeMap<String, ColorsSrgb>,

/// Font aliases, used when searching for a font family matching the key.
#[cfg_attr(feature = "config", serde(default))]
font_aliases: BTreeMap<String, FontAliases>,
}

impl Default for Config {
Expand All @@ -35,6 +43,7 @@ impl Default for Config {
font_size: defaults::font_size(),
active_scheme: Default::default(),
color_schemes: defaults::color_schemes(),
font_aliases: Default::default(),
}
}
}
Expand Down Expand Up @@ -116,6 +125,28 @@ impl ThemeConfig for Config {
fn is_dirty(&self) -> bool {
self.dirty
}

/// Apply config effects which only happen on startup
fn apply_startup(&self) {
if !self.font_aliases.is_empty() {
fonts().update_db(|db| {
for (family, aliases) in self.font_aliases.iter() {
db.add_aliases(
family.to_string().into(),
aliases.list.iter().map(|s| s.to_string().into()),
aliases.mode,
);
}
});
}
}
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "config", derive(serde::Serialize, serde::Deserialize))]
pub struct FontAliases {
mode: AddMode,
list: Vec<String>,
}

mod defaults {
Expand Down
6 changes: 5 additions & 1 deletion kas-theme/src/dim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ impl Dimensions {
let font_id = Default::default();
let dpp = scale_factor * (96.0 / 72.0);
let dpem = dpp * pt_size;
let line_height = i32::conv_ceil(kas::text::fonts::fonts().get(font_id).height(dpem));
let line_height = i32::conv_ceil(
kas::text::fonts::fonts()
.get_first_face(font_id)
.height(dpem),
);

let outer_margin = (params.outer_margin * scale_factor).cast_nearest();
let inner_margin = (params.inner_margin * scale_factor).cast_nearest();
Expand Down
2 changes: 1 addition & 1 deletion kas-theme/src/flat_theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ where
}

fn init(&mut self, _draw: &mut D) {
if let Err(e) = kas::text::fonts::fonts().load_default() {
if let Err(e) = kas::text::fonts::fonts().select_default() {
panic!("Error loading font: {}", e);
}
}
Expand Down
2 changes: 1 addition & 1 deletion kas-theme/src/shaded_theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ where
}

fn init(&mut self, _draw: &mut D) {
if let Err(e) = kas::text::fonts::fonts().load_default() {
if let Err(e) = kas::text::fonts::fonts().select_default() {
panic!("Error loading font: {}", e);
}
}
Expand Down
8 changes: 7 additions & 1 deletion kas-theme/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ use std::ops::{Deref, DerefMut};

/// Requirements on theme config (without `config` feature)
#[cfg(not(feature = "config"))]
pub trait ThemeConfig: Clone + std::fmt::Debug + 'static {}
pub trait ThemeConfig: Clone + std::fmt::Debug + 'static {
/// Apply startup effects
fn apply_startup(&self);
}

/// Requirements on theme config (with `config` feature)
#[cfg(feature = "config")]
Expand All @@ -21,6 +24,9 @@ pub trait ThemeConfig:
{
/// Has the config ever been updated?
fn is_dirty(&self) -> bool;

/// Apply startup effects
fn apply_startup(&self);
}

/// A *theme* provides widget sizing and drawing implementations.
Expand Down
3 changes: 0 additions & 3 deletions kas-wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ gat = ["kas-theme/gat"]
# Enables clipboard read/write
clipboard = ["window_clipboard"]

# Enables text shaping
shaping = ["kas/shaping"]

# Use stack_dst crate for sized unsized types
stack_dst = ["kas-theme/stack_dst"]

Expand Down
Loading