mirror of
https://github.com/wez/wezterm.git
synced 2024-12-22 21:01:36 +03:00
Allow matching font weight and font width in wezterm.font
refs: https://github.com/wez/wezterm/issues/655
This commit is contained in:
parent
dee10c2f21
commit
43ea2f192a
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -697,6 +697,7 @@ dependencies = [
|
|||||||
"bstr 0.2.15",
|
"bstr 0.2.15",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
|
"enum-display-derive",
|
||||||
"filenamegen",
|
"filenamegen",
|
||||||
"hostname",
|
"hostname",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
@ -1070,6 +1071,17 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-display-derive"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f16ef37b2a9b242295d61a154ee91ae884afff6b8b933b486b12481cc58310ca"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enumflags2"
|
name = "enumflags2"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
|
@ -17,6 +17,7 @@ bitflags = "1.0"
|
|||||||
bstr = "0.2"
|
bstr = "0.2"
|
||||||
chrono = {version="0.4", features=["unstable-locales"]}
|
chrono = {version="0.4", features=["unstable-locales"]}
|
||||||
dirs-next = "2.0"
|
dirs-next = "2.0"
|
||||||
|
enum-display-derive = "0.1"
|
||||||
filenamegen = "0.2"
|
filenamegen = "0.2"
|
||||||
hostname = "0.3"
|
hostname = "0.3"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
|
@ -1,9 +1,135 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use bitflags::*;
|
use bitflags::*;
|
||||||
|
use enum_display_derive::Display;
|
||||||
use luahelper::impl_lua_conversion;
|
use luahelper::impl_lua_conversion;
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
use std::fmt::Display;
|
||||||
use termwiz::color::RgbColor;
|
use termwiz::color::RgbColor;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, Display)]
|
||||||
|
pub enum FontWidth {
|
||||||
|
UltraCondensed,
|
||||||
|
ExtraCondensed,
|
||||||
|
Condensed,
|
||||||
|
SemiCondensed,
|
||||||
|
Normal,
|
||||||
|
SemiExpanded,
|
||||||
|
Expanded,
|
||||||
|
ExtraExpanded,
|
||||||
|
UltraExpanded,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontWidth {
|
||||||
|
pub fn from_opentype_width(w: u16) -> Self {
|
||||||
|
match w {
|
||||||
|
1 => Self::UltraCondensed,
|
||||||
|
2 => Self::ExtraCondensed,
|
||||||
|
3 => Self::Condensed,
|
||||||
|
4 => Self::SemiCondensed,
|
||||||
|
5 => Self::Normal,
|
||||||
|
6 => Self::SemiExpanded,
|
||||||
|
7 => Self::Expanded,
|
||||||
|
8 => Self::ExtraExpanded,
|
||||||
|
9 => Self::UltraExpanded,
|
||||||
|
_ if w < 1 => Self::UltraCondensed,
|
||||||
|
_ => Self::UltraExpanded,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_opentype_width(self) -> u16 {
|
||||||
|
match self {
|
||||||
|
Self::UltraCondensed => 1,
|
||||||
|
Self::ExtraCondensed => 2,
|
||||||
|
Self::Condensed => 3,
|
||||||
|
Self::SemiCondensed => 4,
|
||||||
|
Self::Normal => 5,
|
||||||
|
Self::SemiExpanded => 6,
|
||||||
|
Self::Expanded => 7,
|
||||||
|
Self::ExtraExpanded => 8,
|
||||||
|
Self::UltraExpanded => 9,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FontWidth {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Hash, Display)]
|
||||||
|
pub enum FontWeight {
|
||||||
|
Thin,
|
||||||
|
ExtraLight,
|
||||||
|
Light,
|
||||||
|
DemiLight,
|
||||||
|
Book,
|
||||||
|
Regular,
|
||||||
|
Medium,
|
||||||
|
DemiBold,
|
||||||
|
Bold,
|
||||||
|
ExtraBold,
|
||||||
|
Black,
|
||||||
|
ExtraBlack,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for FontWeight {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Regular
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontWeight {
|
||||||
|
pub fn from_opentype_weight(w: u16) -> Self {
|
||||||
|
if w >= 1000 {
|
||||||
|
Self::ExtraBlack
|
||||||
|
} else if w >= 900 {
|
||||||
|
Self::Black
|
||||||
|
} else if w >= 800 {
|
||||||
|
Self::ExtraBold
|
||||||
|
} else if w >= 700 {
|
||||||
|
Self::Bold
|
||||||
|
} else if w >= 600 {
|
||||||
|
Self::DemiBold
|
||||||
|
} else if w >= 500 {
|
||||||
|
Self::Medium
|
||||||
|
} else if w >= 400 {
|
||||||
|
Self::Regular
|
||||||
|
} else if w >= 380 {
|
||||||
|
Self::Book
|
||||||
|
} else if w >= 350 {
|
||||||
|
Self::DemiLight
|
||||||
|
} else if w >= 300 {
|
||||||
|
Self::Light
|
||||||
|
} else if w >= 200 {
|
||||||
|
Self::ExtraLight
|
||||||
|
} else {
|
||||||
|
Self::Thin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_opentype_weight(self) -> u16 {
|
||||||
|
match self {
|
||||||
|
Self::Thin => 100,
|
||||||
|
Self::ExtraLight => 200,
|
||||||
|
Self::Light => 300,
|
||||||
|
Self::DemiLight => 350,
|
||||||
|
Self::Book => 380,
|
||||||
|
Self::Regular => 400,
|
||||||
|
Self::Medium => 500,
|
||||||
|
Self::DemiBold => 600,
|
||||||
|
Self::Bold => 700,
|
||||||
|
Self::ExtraBold => 800,
|
||||||
|
Self::Black => 900,
|
||||||
|
Self::ExtraBlack => 1000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bolder(self) -> Self {
|
||||||
|
Self::from_opentype_weight(self.to_opentype_weight() + 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum FreeTypeLoadTarget {
|
pub enum FreeTypeLoadTarget {
|
||||||
/// This corresponds to the default hinting algorithm, optimized
|
/// This corresponds to the default hinting algorithm, optimized
|
||||||
@ -123,7 +249,9 @@ pub struct FontAttributes {
|
|||||||
pub family: String,
|
pub family: String,
|
||||||
/// Whether the font should be a bold variant
|
/// Whether the font should be a bold variant
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub bold: bool,
|
pub weight: FontWeight,
|
||||||
|
#[serde(default)]
|
||||||
|
pub width: FontWidth,
|
||||||
/// Whether the font should be an italic variant
|
/// Whether the font should be an italic variant
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub italic: bool,
|
pub italic: bool,
|
||||||
@ -136,8 +264,8 @@ impl std::fmt::Display for FontAttributes {
|
|||||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
|
||||||
write!(
|
write!(
|
||||||
fmt,
|
fmt,
|
||||||
"wezterm.font('{}', {{bold={}, italic={}}})",
|
"wezterm.font('{}', {{weight='{}', width='{}', italic={}}})",
|
||||||
self.family, self.bold, self.italic
|
self.family, self.weight, self.width, self.italic
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +274,8 @@ impl FontAttributes {
|
|||||||
pub fn new(family: &str) -> Self {
|
pub fn new(family: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
family: family.into(),
|
family: family.into(),
|
||||||
bold: false,
|
weight: FontWeight::default(),
|
||||||
|
width: FontWidth::default(),
|
||||||
italic: false,
|
italic: false,
|
||||||
is_fallback: false,
|
is_fallback: false,
|
||||||
is_synthetic: false,
|
is_synthetic: false,
|
||||||
@ -156,7 +285,8 @@ impl FontAttributes {
|
|||||||
pub fn new_fallback(family: &str) -> Self {
|
pub fn new_fallback(family: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
family: family.into(),
|
family: family.into(),
|
||||||
bold: false,
|
weight: FontWeight::default(),
|
||||||
|
width: FontWidth::default(),
|
||||||
italic: false,
|
italic: false,
|
||||||
is_fallback: true,
|
is_fallback: true,
|
||||||
is_synthetic: false,
|
is_synthetic: false,
|
||||||
@ -168,7 +298,8 @@ impl Default for FontAttributes {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
family: "JetBrains Mono".into(),
|
family: "JetBrains Mono".into(),
|
||||||
bold: false,
|
weight: FontWeight::default(),
|
||||||
|
width: FontWidth::default(),
|
||||||
italic: false,
|
italic: false,
|
||||||
is_fallback: false,
|
is_fallback: false,
|
||||||
is_synthetic: false,
|
is_synthetic: false,
|
||||||
@ -269,7 +400,7 @@ impl TextStyle {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|attr| {
|
.map(|attr| {
|
||||||
let mut attr = attr.clone();
|
let mut attr = attr.clone();
|
||||||
attr.bold = true;
|
attr.weight = attr.weight.bolder();
|
||||||
attr.is_synthetic = true;
|
attr.is_synthetic = true;
|
||||||
attr
|
attr
|
||||||
})
|
})
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{FontAttributes, TextStyle};
|
use crate::{FontAttributes, FontWeight, FontWidth, TextStyle};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use bstr::BString;
|
use bstr::BString;
|
||||||
pub use luahelper::*;
|
pub use luahelper::*;
|
||||||
@ -334,7 +334,11 @@ fn hostname<'lua>(_: &'lua Lua, _: ()) -> mlua::Result<String> {
|
|||||||
struct TextStyleAttributes {
|
struct TextStyleAttributes {
|
||||||
/// Whether the font should be a bold variant
|
/// Whether the font should be a bold variant
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub bold: bool,
|
pub bold: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub weight: Option<FontWeight>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub width: FontWidth,
|
||||||
/// Whether the font should be an italic variant
|
/// Whether the font should be an italic variant
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub italic: bool,
|
pub italic: bool,
|
||||||
@ -365,7 +369,12 @@ fn font<'lua>(
|
|||||||
text_style.font.clear();
|
text_style.font.clear();
|
||||||
text_style.font.push(FontAttributes {
|
text_style.font.push(FontAttributes {
|
||||||
family,
|
family,
|
||||||
bold: attrs.bold,
|
width: attrs.width,
|
||||||
|
weight: match attrs.bold {
|
||||||
|
Some(true) => FontWeight::Bold,
|
||||||
|
Some(false) => FontWeight::Regular,
|
||||||
|
None => attrs.weight.unwrap_or(FontWeight::Regular),
|
||||||
|
},
|
||||||
italic: attrs.italic,
|
italic: attrs.italic,
|
||||||
is_fallback: false,
|
is_fallback: false,
|
||||||
is_synthetic: false,
|
is_synthetic: false,
|
||||||
@ -393,7 +402,12 @@ fn font_with_fallback<'lua>(
|
|||||||
for (idx, family) in fallback.into_iter().enumerate() {
|
for (idx, family) in fallback.into_iter().enumerate() {
|
||||||
text_style.font.push(FontAttributes {
|
text_style.font.push(FontAttributes {
|
||||||
family,
|
family,
|
||||||
bold: attrs.bold,
|
width: attrs.width,
|
||||||
|
weight: match attrs.bold {
|
||||||
|
Some(true) => FontWeight::Bold,
|
||||||
|
Some(false) => FontWeight::Regular,
|
||||||
|
None => attrs.weight.unwrap_or(FontWeight::Regular),
|
||||||
|
},
|
||||||
italic: attrs.italic,
|
italic: attrs.italic,
|
||||||
is_fallback: idx != 0,
|
is_fallback: idx != 0,
|
||||||
is_synthetic: false,
|
is_synthetic: false,
|
||||||
|
10
deps/fontconfig/src/lib.rs
vendored
10
deps/fontconfig/src/lib.rs
vendored
@ -52,6 +52,16 @@ pub const FC_SLANT_ROMAN: c_int = 0;
|
|||||||
pub const FC_SLANT_ITALIC: c_int = 100;
|
pub const FC_SLANT_ITALIC: c_int = 100;
|
||||||
pub const FC_SLANT_OBLIQUE: c_int = 110;
|
pub const FC_SLANT_OBLIQUE: c_int = 110;
|
||||||
|
|
||||||
|
pub const FC_WIDTH_ULTRACONDENSED: c_int = 50;
|
||||||
|
pub const FC_WIDTH_EXTRACONDENSED: c_int = 63;
|
||||||
|
pub const FC_WIDTH_CONDENSED: c_int = 75;
|
||||||
|
pub const FC_WIDTH_SEMICONDENSED: c_int = 87;
|
||||||
|
pub const FC_WIDTH_NORMAL: c_int = 100;
|
||||||
|
pub const FC_WIDTH_SEMIEXPANDED: c_int = 113;
|
||||||
|
pub const FC_WIDTH_EXPANDED: c_int = 125;
|
||||||
|
pub const FC_WIDTH_EXTRAEXPANDED: c_int = 150;
|
||||||
|
pub const FC_WIDTH_ULTRAEXPANDED: c_int = 200;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct struct__FcMatrix {
|
pub struct struct__FcMatrix {
|
||||||
|
@ -15,6 +15,7 @@ As features stabilize some brief notes about them will accumulate here.
|
|||||||
* Fixed: the selection wouldn't always clear when the intersecting lines change [#644](https://github.com/wez/wezterm/issues/644)
|
* Fixed: the selection wouldn't always clear when the intersecting lines change [#644](https://github.com/wez/wezterm/issues/644)
|
||||||
* Fixed: vertical alignment issue with Iosevka on Windows [#661](https://github.com/wez/wezterm/issues/661)
|
* Fixed: vertical alignment issue with Iosevka on Windows [#661](https://github.com/wez/wezterm/issues/661)
|
||||||
* Fixed: support for "Variable" fonts such as Cascadia Code and Inconsolata on all platforms [#655](https://github.com/wez/wezterm/issues/655)
|
* Fixed: support for "Variable" fonts such as Cascadia Code and Inconsolata on all platforms [#655](https://github.com/wez/wezterm/issues/655)
|
||||||
|
* New: [wezterm.font](config/lua/wezterm/font.md) and [wezterm.font_with_fallback](config/lua/wezterm.font_with_fallback.md) *attributes* parameter now allows matching more granular font weights and font widths. e.g.: `wezterm.font('Iosevka Term', {width="Expanded", weight="Regular"})`
|
||||||
|
|
||||||
### 20210405-110924-a5bb5be8
|
### 20210405-110924-a5bb5be8
|
||||||
|
|
||||||
|
@ -25,4 +25,21 @@ return {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
*Since: nightly builds only*
|
||||||
|
|
||||||
|
It is now possible to specify both font weight and font width:
|
||||||
|
|
||||||
|
* `width` - specifies the font width to select. The default value is `"Normal"`, and possible values are `"UltraCondensed"`, `"ExtraCondensed"`, `"Condensed"`, `"SemiCondensed"`, `"Normal"`, `"SemiExpanded"`, `"Expanded"`, `"ExtraExpanded"`, `"UltraExpanded"`.
|
||||||
|
* `weight` - specifies the weight of the font with more precision than `bold`. The default value is `"Regular"`, and possible values are `"Thin"`, `"ExtraLight"`, `"Light"`, `"DemiLight"`, `"Book"`, `"Regular"`, `"Medium"`, `"DemiBold"`, `"Bold"`, `"ExtraBold"`, `"Black"`, and `"ExtraBlack"`.
|
||||||
|
* `bold` - has been superseded by the new `weight` parameter and will be eventually removed. For compatibility purposes, specifying `bold=true` is equivalent to specifying `weight="Bold"`.
|
||||||
|
|
||||||
|
Font weight matching will find the closest matching weight that is equal of
|
||||||
|
heavier to the specified weight.
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local wezterm = require 'wezterm';
|
||||||
|
|
||||||
|
return {
|
||||||
|
font = wezterm.font('Iosevka Term', {width="Expanded", weight="Regular"}),
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -14,6 +14,7 @@ return {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The second parameter behaves the same as that of `wezterm.font`.
|
The *attributes* parameter behaves the same as that of [wezterm.font](font.md)
|
||||||
|
in that it allows you to specify font weight and style attributes that you
|
||||||
|
want to match.
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#![allow(clippy::mutex_atomic)]
|
#![allow(clippy::mutex_atomic)]
|
||||||
|
|
||||||
use anyhow::{anyhow, ensure, Error};
|
use anyhow::{anyhow, ensure, Error};
|
||||||
|
use config::{FontWeight, FontWidth};
|
||||||
pub use fontconfig::*;
|
pub use fontconfig::*;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@ -446,3 +447,33 @@ impl fmt::Debug for Pattern {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_fc_weight(weight: FontWeight) -> c_int {
|
||||||
|
match weight {
|
||||||
|
FontWeight::Thin => FC_WEIGHT_THIN,
|
||||||
|
FontWeight::ExtraLight => FC_WEIGHT_EXTRALIGHT,
|
||||||
|
FontWeight::Light => FC_WEIGHT_LIGHT,
|
||||||
|
FontWeight::DemiLight | FontWeight::Book => FC_WEIGHT_BOOK,
|
||||||
|
FontWeight::Regular => FC_WEIGHT_REGULAR,
|
||||||
|
FontWeight::Medium => FC_WEIGHT_MEDIUM,
|
||||||
|
FontWeight::DemiBold => FC_WEIGHT_DEMIBOLD,
|
||||||
|
FontWeight::Bold => FC_WEIGHT_BOLD,
|
||||||
|
FontWeight::ExtraBold => FC_WEIGHT_EXTRABOLD,
|
||||||
|
FontWeight::Black => FC_WEIGHT_BLACK,
|
||||||
|
FontWeight::ExtraBlack => FC_WEIGHT_EXTRABLACK,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_fc_width(width: FontWidth) -> c_int {
|
||||||
|
match width {
|
||||||
|
FontWidth::UltraCondensed => FC_WIDTH_ULTRACONDENSED,
|
||||||
|
FontWidth::ExtraCondensed => FC_WIDTH_EXTRACONDENSED,
|
||||||
|
FontWidth::Condensed => FC_WIDTH_CONDENSED,
|
||||||
|
FontWidth::SemiCondensed => FC_WIDTH_SEMICONDENSED,
|
||||||
|
FontWidth::Normal => FC_WIDTH_NORMAL,
|
||||||
|
FontWidth::SemiExpanded => FC_WIDTH_SEMIEXPANDED,
|
||||||
|
FontWidth::Expanded => FC_WIDTH_EXPANDED,
|
||||||
|
FontWidth::ExtraExpanded => FC_WIDTH_EXTRAEXPANDED,
|
||||||
|
FontWidth::UltraExpanded => FC_WIDTH_ULTRAEXPANDED,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,7 +3,9 @@ use crate::locator::{new_locator, FontDataHandle, FontLocator};
|
|||||||
use crate::rasterizer::{new_rasterizer, FontRasterizer};
|
use crate::rasterizer::{new_rasterizer, FontRasterizer};
|
||||||
use crate::shaper::{new_shaper, FontShaper};
|
use crate::shaper::{new_shaper, FontShaper};
|
||||||
use anyhow::{Context, Error};
|
use anyhow::{Context, Error};
|
||||||
use config::{configuration, ConfigHandle, FontRasterizerSelection, TextStyle};
|
use config::{
|
||||||
|
configuration, ConfigHandle, FontRasterizerSelection, FontWeight, FontWidth, TextStyle,
|
||||||
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::rc::{Rc, Weak};
|
use std::rc::{Rc, Weak};
|
||||||
@ -281,8 +283,11 @@ impl FontConfigInner {
|
|||||||
|
|
||||||
for attr in &attributes {
|
for attr in &attributes {
|
||||||
if !attr.is_synthetic && !attr.is_fallback && !loaded.contains(attr) {
|
if !attr.is_synthetic && !attr.is_fallback && !loaded.contains(attr) {
|
||||||
let styled_extra = if attr.bold || attr.italic {
|
let styled_extra = if attr.weight != FontWeight::default()
|
||||||
". A bold or italic variant of the font was requested; \
|
|| attr.italic
|
||||||
|
|| attr.width != FontWidth::default()
|
||||||
|
{
|
||||||
|
". An alternative variant of the font was requested; \
|
||||||
TrueType and OpenType fonts don't have an automatic way to \
|
TrueType and OpenType fonts don't have an automatic way to \
|
||||||
produce these font variants, so a separate font file containing \
|
produce these font variants, so a separate font file containing \
|
||||||
the bold or italic variant must be installed"
|
the bold or italic variant must be installed"
|
||||||
|
@ -3,7 +3,7 @@ use crate::locator::{FontDataHandle, FontDataSource, FontLocator};
|
|||||||
use crate::parser::FontMatch;
|
use crate::parser::FontMatch;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use config::FontAttributes;
|
use config::FontAttributes;
|
||||||
use fcwrap::{CharSet, Pattern as FontPattern};
|
use fcwrap::{to_fc_weight, to_fc_width, CharSet, Pattern as FontPattern};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
@ -28,8 +28,16 @@ impl FontLocator for FontConfigFontLocator {
|
|||||||
let mut pattern = FontPattern::new()?;
|
let mut pattern = FontPattern::new()?;
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
pattern.family(&attr.family)?;
|
pattern.family(&attr.family)?;
|
||||||
pattern.add_integer("weight", if attr.bold { 200 } else { 80 })?;
|
pattern.add_integer("weight", to_fc_weight(attr.weight))?;
|
||||||
pattern.add_integer("slant", if attr.italic { 100 } else { 0 })?;
|
pattern.add_integer("width", to_fc_width(attr.width))?;
|
||||||
|
pattern.add_integer(
|
||||||
|
"slant",
|
||||||
|
if attr.italic {
|
||||||
|
fcwrap::FC_SLANT_ITALIC
|
||||||
|
} else {
|
||||||
|
fcwrap::FC_SLANT_ROMAN
|
||||||
|
},
|
||||||
|
)?;
|
||||||
pattern.add_integer("spacing", spacing)?;
|
pattern.add_integer("spacing", spacing)?;
|
||||||
|
|
||||||
log::trace!("fc pattern before config subst: {:?}", pattern);
|
log::trace!("fc pattern before config subst: {:?}", pattern);
|
||||||
@ -44,10 +52,13 @@ impl FontLocator for FontConfigFontLocator {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let file = best.get_file()?;
|
let file = best.get_file()?;
|
||||||
|
let index = best.get_integer("index")? as u32;
|
||||||
|
let variation = index >> 16;
|
||||||
|
let index = index & 0xffff;
|
||||||
let handle = FontDataHandle {
|
let handle = FontDataHandle {
|
||||||
source: FontDataSource::OnDisk(file.into()),
|
source: FontDataSource::OnDisk(file.into()),
|
||||||
index: best.get_integer("index")?.try_into()?,
|
index,
|
||||||
variation: 0,
|
variation,
|
||||||
};
|
};
|
||||||
|
|
||||||
// fontconfig will give us a boatload of random fallbacks.
|
// fontconfig will give us a boatload of random fallbacks.
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::locator::{FontDataHandle, FontDataSource, FontLocator};
|
use crate::locator::{FontDataHandle, FontDataSource, FontLocator};
|
||||||
use crate::parser::{parse_and_collect_font_info, rank_matching_fonts, FontMatch, ParsedFont};
|
use crate::parser::{parse_and_collect_font_info, rank_matching_fonts, FontMatch, ParsedFont};
|
||||||
use config::FontAttributes;
|
use config::{FontAttributes, FontWeight as WTFontWeight, FontWidth};
|
||||||
use dwrote::{FontDescriptor, FontStretch, FontStyle, FontWeight};
|
use dwrote::{FontDescriptor, FontStretch, FontStyle, FontWeight};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -88,7 +88,7 @@ fn load_font(font_attr: &FontAttributes) -> anyhow::Result<FontDataHandle> {
|
|||||||
lfWidth: 0,
|
lfWidth: 0,
|
||||||
lfEscapement: 0,
|
lfEscapement: 0,
|
||||||
lfOrientation: 0,
|
lfOrientation: 0,
|
||||||
lfWeight: if font_attr.bold { 700 } else { 0 },
|
lfWeight: font_attr.weight.to_opentype_weight() as _,
|
||||||
lfItalic: if font_attr.italic { 1 } else { 0 },
|
lfItalic: if font_attr.italic { 1 } else { 0 },
|
||||||
lfUnderline: 0,
|
lfUnderline: 0,
|
||||||
lfStrikeOut: 0,
|
lfStrikeOut: 0,
|
||||||
@ -122,11 +122,7 @@ fn load_font(font_attr: &FontAttributes) -> anyhow::Result<FontDataHandle> {
|
|||||||
fn attributes_to_descriptor(font_attr: &FontAttributes) -> FontDescriptor {
|
fn attributes_to_descriptor(font_attr: &FontAttributes) -> FontDescriptor {
|
||||||
FontDescriptor {
|
FontDescriptor {
|
||||||
family_name: font_attr.family.to_string(),
|
family_name: font_attr.family.to_string(),
|
||||||
weight: if font_attr.bold {
|
weight: FontWeight::from_u32(font_attr.weight.to_opentype_weight() as u32),
|
||||||
FontWeight::Bold
|
|
||||||
} else {
|
|
||||||
FontWeight::Regular
|
|
||||||
},
|
|
||||||
stretch: FontStretch::Normal,
|
stretch: FontStretch::Normal,
|
||||||
style: if font_attr.italic {
|
style: if font_attr.italic {
|
||||||
FontStyle::Italic
|
FontStyle::Italic
|
||||||
@ -282,20 +278,8 @@ impl FontLocator for GdiFontLocator {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let attr = FontAttributes {
|
let attr = FontAttributes {
|
||||||
bold: match font.weight() {
|
weight: WTFontWeight::from_opentype_weight(font.weight().to_u32() as _),
|
||||||
FontWeight::Thin
|
width: FontWidth::from_opentype_width(font.stretch().to_u32() as _),
|
||||||
| FontWeight::ExtraLight
|
|
||||||
| FontWeight::Light
|
|
||||||
| FontWeight::SemiLight
|
|
||||||
| FontWeight::Regular
|
|
||||||
| FontWeight::Medium => false,
|
|
||||||
FontWeight::SemiBold
|
|
||||||
| FontWeight::Bold
|
|
||||||
| FontWeight::ExtraBold
|
|
||||||
| FontWeight::Black
|
|
||||||
| FontWeight::ExtraBlack => true,
|
|
||||||
FontWeight::Unknown(n) => n > 80,
|
|
||||||
},
|
|
||||||
italic: false,
|
italic: false,
|
||||||
family: font.family_name(),
|
family: font.family_name(),
|
||||||
is_fallback: true,
|
is_fallback: true,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::locator::{FontDataHandle, FontDataSource};
|
use crate::locator::{FontDataHandle, FontDataSource};
|
||||||
use crate::shaper::GlyphInfo;
|
use crate::shaper::GlyphInfo;
|
||||||
use config::FontAttributes;
|
use config::FontAttributes;
|
||||||
|
pub use config::{FontWeight, FontWidth};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -9,100 +10,6 @@ pub enum MaybeShaped {
|
|||||||
Unresolved { raw: String, slice_start: usize },
|
Unresolved { raw: String, slice_start: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum FontWidth {
|
|
||||||
UltraCondensed,
|
|
||||||
ExtraCondensed,
|
|
||||||
Condensed,
|
|
||||||
SemiCondensed,
|
|
||||||
Normal,
|
|
||||||
SemiExpanded,
|
|
||||||
Expanded,
|
|
||||||
ExtraExpanded,
|
|
||||||
UltraExpanded,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FontWidth {
|
|
||||||
pub fn from_opentype_width(w: u16) -> Self {
|
|
||||||
match w {
|
|
||||||
1 => Self::UltraCondensed,
|
|
||||||
2 => Self::ExtraCondensed,
|
|
||||||
3 => Self::Condensed,
|
|
||||||
4 => Self::SemiCondensed,
|
|
||||||
5 => Self::Normal,
|
|
||||||
6 => Self::SemiExpanded,
|
|
||||||
7 => Self::Expanded,
|
|
||||||
8 => Self::ExtraExpanded,
|
|
||||||
9 => Self::UltraExpanded,
|
|
||||||
_ if w < 1 => Self::UltraCondensed,
|
|
||||||
_ => Self::UltraExpanded,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum FontWeight {
|
|
||||||
Thin,
|
|
||||||
ExtraLight,
|
|
||||||
Light,
|
|
||||||
DemiLight,
|
|
||||||
Book,
|
|
||||||
Regular,
|
|
||||||
Medium,
|
|
||||||
DemiBold,
|
|
||||||
Bold,
|
|
||||||
ExtraBold,
|
|
||||||
Black,
|
|
||||||
ExtraBlack,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FontWeight {
|
|
||||||
pub fn from_opentype_weight(w: u16) -> Self {
|
|
||||||
if w >= 1000 {
|
|
||||||
Self::ExtraBlack
|
|
||||||
} else if w >= 900 {
|
|
||||||
Self::Black
|
|
||||||
} else if w >= 800 {
|
|
||||||
Self::ExtraBold
|
|
||||||
} else if w >= 700 {
|
|
||||||
Self::Bold
|
|
||||||
} else if w >= 600 {
|
|
||||||
Self::DemiBold
|
|
||||||
} else if w >= 500 {
|
|
||||||
Self::Medium
|
|
||||||
} else if w >= 400 {
|
|
||||||
Self::Regular
|
|
||||||
} else if w >= 380 {
|
|
||||||
Self::Book
|
|
||||||
} else if w >= 350 {
|
|
||||||
Self::DemiLight
|
|
||||||
} else if w >= 300 {
|
|
||||||
Self::Light
|
|
||||||
} else if w >= 200 {
|
|
||||||
Self::ExtraLight
|
|
||||||
} else {
|
|
||||||
Self::Thin
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_opentype_weight(self) -> u16 {
|
|
||||||
match self {
|
|
||||||
Self::Thin => 100,
|
|
||||||
Self::ExtraLight => 200,
|
|
||||||
Self::Light => 300,
|
|
||||||
Self::DemiLight => 350,
|
|
||||||
Self::Book => 380,
|
|
||||||
Self::Regular => 400,
|
|
||||||
Self::Medium => 500,
|
|
||||||
Self::DemiBold => 600,
|
|
||||||
Self::Bold => 700,
|
|
||||||
Self::ExtraBold => 800,
|
|
||||||
Self::Black => 900,
|
|
||||||
Self::ExtraBlack => 1000,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a parsed font
|
/// Represents a parsed font
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParsedFont {
|
pub struct ParsedFont {
|
||||||
@ -183,14 +90,8 @@ impl ParsedFont {
|
|||||||
pub fn matches_attributes(&self, attr: &FontAttributes) -> FontMatch {
|
pub fn matches_attributes(&self, attr: &FontAttributes) -> FontMatch {
|
||||||
if let Some(fam) = self.names.family.as_ref() {
|
if let Some(fam) = self.names.family.as_ref() {
|
||||||
if attr.family == *fam {
|
if attr.family == *fam {
|
||||||
let wanted_width = FontWidth::Normal;
|
if attr.width == self.width {
|
||||||
if wanted_width == self.width {
|
let wanted_weight = attr.weight.to_opentype_weight();
|
||||||
let wanted_weight = if attr.bold {
|
|
||||||
FontWeight::Bold
|
|
||||||
} else {
|
|
||||||
FontWeight::Regular
|
|
||||||
}
|
|
||||||
.to_opentype_weight();
|
|
||||||
let weight = self.weight.to_opentype_weight();
|
let weight = self.weight.to_opentype_weight();
|
||||||
|
|
||||||
if weight >= wanted_weight {
|
if weight >= wanted_weight {
|
||||||
|
Loading…
Reference in New Issue
Block a user