Add font weight options (#6048)

## Summary of the Pull Request
Adds the ability to specify the font weight in the profiles, right next to the size and the font face.

## PR Checklist
* [x] Closes #1751 
* [x] I work here.
* [x] Tested manually, see below.
* [x] Added documentation to the schema 
* [x] Requires docs.microsoft.com update, filed as https://github.com/MicrosoftDocs/terminal/issues/26
* [x] I'm a core contributor.

## Detailed Description of the Pull Request / Additional comments
- Weights can be specified according to the OpenType specification values. We accept either the friendly name or the numerical value that applies to each weight.
- Weights are carried through per-profile and sent into the renderer.
- Weights are carried through to the TSF/IME overlay.
- The names are restricted to the set seen at https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.fontweights.
- There are alternate names at https://docs.microsoft.com/en-us/windows/win32/api/dwrite/ne-dwrite-dwrite_font_weight for the same values (ultra-black is just an alias for extra-black at 950).

## Validation Steps Performed
- Cascadia Code normal
![image](https://user-images.githubusercontent.com/18221333/82480181-46117380-9a88-11ea-9436-a5fe4ccd4350.png)

- Cascadia Code bold
![image](https://user-images.githubusercontent.com/18221333/82480202-4f9adb80-9a88-11ea-9e27-a113b41387f5.png)

- Segoe UI Semilight
![image](https://user-images.githubusercontent.com/18221333/82480306-73f6b800-9a88-11ea-93f7-d773ab7ccce8.png)

- Segoe UI Black
![image](https://user-images.githubusercontent.com/18221333/82480401-9688d100-9a88-11ea-957c-0c8e03a8cc29.png)

- Segoe UI 900 (value for Black)
![image](https://user-images.githubusercontent.com/18221333/82480774-26c71600-9a89-11ea-8cf6-aaeab1fd0747.png)
This commit is contained in:
Michael Niksa 2020-05-20 13:17:17 -07:00 committed by GitHub
parent 99a6fa4421
commit 8265d941b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 159 additions and 6 deletions

View file

@ -47,6 +47,7 @@ Properties listed below are specific to each unique profile.
| `cursorShape` | Optional | String | `bar` | Sets the cursor shape for the profile. Possible values: `"vintage"` ( ▃ ), `"bar"` ( ┃ ), `"underscore"` ( ▁ ), `"filledBox"` ( █ ), `"emptyBox"` ( ▯ ) |
| `fontFace` | Optional | String | `Cascadia Mono` | Name of the font face used in the profile. We will try to fallback to Consolas if this can't be found or is invalid. |
| `fontSize` | Optional | Integer | `12` | Sets the font size. |
| `fontWeight` | Optional | String | `normal` | Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values: `"thin"`, `"extra-light"`, `"light"`, `"semi-light"`, `"normal"`, `"medium"`, `"semi-bold"`, `"bold"`, `"extra-bold"`, `"black"`, `"extra-black"`, or the corresponding numeric representation of OpenType font weight. |
| `foreground` | Optional | String | | Sets the foreground color of the profile. Overrides `foreground` set in color scheme if `colorscheme` is set. Uses hex color format: `#rgb` or `"#rrggbb"`. |
| `hidden` | Optional | Boolean | `false` | If set to true, the profile will not appear in the list of profiles. This can be used to hide default profiles and dynamically generated profiles, while leaving them in your settings file. |
| `historySize` | Optional | Integer | `9001` | The number of lines above the ones displayed in the window you can scroll back to. |

View file

@ -531,6 +531,32 @@
"minimum": 1,
"type": "integer"
},
"fontWeight": {
"default": "normal",
"description": "Sets the weight (lightness or heaviness of the strokes) for the given font. Possible values:\n -\"thin\"\n -\"extra-light\"\n -\"light\"\n -\"semi-light\"\n -\"normal\" (default)\n -\"medium\"\n -\"semi-bold\"\n -\"bold\"\n -\"extra-bold\"\n -\"black\"\n -\"extra-black\" or the corresponding numeric representation of OpenType font weight.",
"oneOf": [
{
"enum": [
"thin",
"extra-light",
"light",
"semi-light",
"normal",
"medium",
"semi-bold",
"bold",
"extra-bold",
"black",
"extra-black"
],
"type": "string"
},
{
"maximum": 990,
"minimum": 100,
"type": "integer"
}
}
"foreground": {
"$ref": "#/definitions/Color",
"default": "#cccccc",

View file

@ -36,6 +36,7 @@ static constexpr std::string_view ConnectionTypeKey{ "connectionType" };
static constexpr std::string_view CommandlineKey{ "commandline" };
static constexpr std::string_view FontFaceKey{ "fontFace" };
static constexpr std::string_view FontSizeKey{ "fontSize" };
static constexpr std::string_view FontWeightKey{ "fontWeight" };
static constexpr std::string_view AcrylicTransparencyKey{ "acrylicOpacity" };
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
@ -66,6 +67,19 @@ static constexpr std::wstring_view CursorShapeUnderscore{ L"underscore" };
static constexpr std::wstring_view CursorShapeFilledbox{ L"filledBox" };
static constexpr std::wstring_view CursorShapeEmptybox{ L"emptyBox" };
// Possible values for Font Weight
static constexpr std::string_view FontWeightThin{ "thin" };
static constexpr std::string_view FontWeightExtraLight{ "extra-light" };
static constexpr std::string_view FontWeightLight{ "light" };
static constexpr std::string_view FontWeightSemiLight{ "semi-light" };
static constexpr std::string_view FontWeightNormal{ "normal" };
static constexpr std::string_view FontWeightMedium{ "medium" };
static constexpr std::string_view FontWeightSemiBold{ "semi-bold" };
static constexpr std::string_view FontWeightBold{ "bold" };
static constexpr std::string_view FontWeightExtraBold{ "extra-bold" };
static constexpr std::string_view FontWeightBlack{ "black" };
static constexpr std::string_view FontWeightExtraBlack{ "extra-black" };
// Possible values for Image Stretch Mode
static constexpr std::string_view ImageStretchModeNone{ "none" };
static constexpr std::string_view ImageStretchModeFill{ "fill" };
@ -115,6 +129,7 @@ Profile::Profile(const std::optional<GUID>& guid) :
_startingDirectory{},
_fontFace{ DEFAULT_FONT_FACE },
_fontSize{ DEFAULT_FONT_SIZE },
/* _fontWeight is initialized below because the structure won't accept a uint16_t directly */
_acrylicTransparency{ 0.5 },
_useAcrylic{ false },
_scrollbarState{},
@ -128,6 +143,9 @@ Profile::Profile(const std::optional<GUID>& guid) :
_retroTerminalEffect{},
_antialiasingMode{ TextAntialiasingMode::Grayscale }
{
winrt::Windows::UI::Text::FontWeight weight;
weight.Weight = DEFAULT_FONT_WEIGHT;
_fontWeight = weight;
}
Profile::~Profile()
@ -180,6 +198,7 @@ TerminalSettings Profile::CreateTerminalSettings(const std::unordered_map<std::w
terminalSettings.FontFace(_fontFace);
terminalSettings.FontSize(_fontSize);
terminalSettings.FontWeight(_fontWeight);
terminalSettings.Padding(_padding);
terminalSettings.Commandline(_commandline);
@ -474,6 +493,12 @@ void Profile::LayerJson(const Json::Value& json)
JsonUtils::GetInt(json, FontSizeKey, _fontSize);
if (json.isMember(JsonKey(FontWeightKey)))
{
auto fontWeight{ json[JsonKey(FontWeightKey)] };
_fontWeight = _ParseFontWeight(fontWeight);
}
JsonUtils::GetDouble(json, AcrylicTransparencyKey, _acrylicTransparency);
JsonUtils::GetBool(json, UseAcrylicKey, _useAcrylic);
@ -740,6 +765,78 @@ std::wstring Profile::EvaluateStartingDirectory(const std::wstring& directory)
}
}
// Method Description:
// - Helper function for converting a user-specified font weight value to its corresponding enum
// Arguments:
// - The value from the settings.json file
// Return Value:
// - The corresponding value which maps to the string provided by the user
winrt::Windows::UI::Text::FontWeight Profile::_ParseFontWeight(const Json::Value& json)
{
if (json.isUInt())
{
winrt::Windows::UI::Text::FontWeight weight;
weight.Weight = static_cast<uint16_t>(json.asUInt());
// We're only accepting variable values between 100 and 990 so we don't go too crazy.
if (weight.Weight >= 100 && weight.Weight <= 990)
{
return weight;
}
}
if (json.isString())
{
auto fontWeight = json.asString();
if (fontWeight == FontWeightThin)
{
return winrt::Windows::UI::Text::FontWeights::Thin();
}
else if (fontWeight == FontWeightExtraLight)
{
return winrt::Windows::UI::Text::FontWeights::ExtraLight();
}
else if (fontWeight == FontWeightLight)
{
return winrt::Windows::UI::Text::FontWeights::Light();
}
else if (fontWeight == FontWeightSemiLight)
{
return winrt::Windows::UI::Text::FontWeights::SemiLight();
}
else if (fontWeight == FontWeightNormal)
{
return winrt::Windows::UI::Text::FontWeights::Normal();
}
else if (fontWeight == FontWeightMedium)
{
return winrt::Windows::UI::Text::FontWeights::Medium();
}
else if (fontWeight == FontWeightSemiBold)
{
return winrt::Windows::UI::Text::FontWeights::SemiBold();
}
else if (fontWeight == FontWeightBold)
{
return winrt::Windows::UI::Text::FontWeights::Bold();
}
else if (fontWeight == FontWeightExtraBold)
{
return winrt::Windows::UI::Text::FontWeights::ExtraBold();
}
else if (fontWeight == FontWeightBlack)
{
return winrt::Windows::UI::Text::FontWeights::Black();
}
else if (fontWeight == FontWeightExtraBlack)
{
return winrt::Windows::UI::Text::FontWeights::ExtraBlack();
}
}
return winrt::Windows::UI::Text::FontWeights::Normal();
}
// Method Description:
// - Helper function for converting a user-specified closeOnExit value to its corresponding enum
// Arguments:

View file

@ -114,6 +114,8 @@ private:
static std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> ParseImageAlignment(const std::string_view imageAlignment);
static std::tuple<winrt::Windows::UI::Xaml::HorizontalAlignment, winrt::Windows::UI::Xaml::VerticalAlignment> _ConvertJsonToAlignment(const Json::Value& json);
static winrt::Windows::UI::Text::FontWeight _ParseFontWeight(const Json::Value& json);
static CloseOnExitMode ParseCloseOnExitMode(const Json::Value& json);
static std::string_view _SerializeCloseOnExitMode(const CloseOnExitMode closeOnExitMode);
@ -152,6 +154,7 @@ private:
std::wstring _fontFace;
std::optional<std::wstring> _startingDirectory;
int32_t _fontSize;
winrt::Windows::UI::Text::FontWeight _fontWeight;
double _acrylicTransparency;
bool _useAcrylic;

View file

@ -201,6 +201,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// things in DIPs, and the fontSize is in pixels.
TextBlock().FontSize(unscaledFontSizePx);
TextBlock().FontFamily(Media::FontFamily(fontArgs->FontFace()));
TextBlock().FontWeight(fontArgs->FontWeight());
// TextBlock's actual dimensions right after initialization is 0w x 0h. So,
// if an IME is displayed before TextBlock has text (like showing the emoji picker

View file

@ -27,6 +27,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
GETSET_PROPERTY(Windows::Foundation::Size, FontSize);
GETSET_PROPERTY(winrt::hstring, FontFace);
GETSET_PROPERTY(Windows::UI::Text::FontWeight, FontWeight);
};
struct TSFInputControl : TSFInputControlT<TSFInputControl>

View file

@ -14,6 +14,7 @@ namespace Microsoft.Terminal.TerminalControl
{
String FontFace { get; set; };
Windows.Foundation.Size FontSize { get; set; };
Windows.UI.Text.FontWeight FontWeight { get; set; };
}
[default_interface]

View file

@ -63,8 +63,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_autoScrollingPointerPoint{ std::nullopt },
_autoScrollTimer{},
_lastAutoScrollUpdateTime{ std::nullopt },
_desiredFont{ DEFAULT_FONT_FACE, 0, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, 10, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false },
_desiredFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8 },
_actualFont{ DEFAULT_FONT_FACE, 0, DEFAULT_FONT_WEIGHT, { 0, DEFAULT_FONT_SIZE }, CP_UTF8, false },
_touchAnchor{ std::nullopt },
_cursorTimer{},
_lastMouseClickTimestamp{},
@ -263,13 +263,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// Initialize our font information.
const auto fontFace = _settings.FontFace();
const short fontHeight = gsl::narrow_cast<short>(_settings.FontSize());
const auto fontWeight = _settings.FontWeight();
// The font width doesn't terribly matter, we'll only be using the
// height to look it up
// The other params here also largely don't matter.
// The family is only used to determine if the font is truetype or
// not, but DX doesn't use that info at all.
// The Codepage is additionally not actually used by the DX engine at all.
_actualFont = { fontFace, 0, 10, { 0, fontHeight }, CP_UTF8, false };
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false };
_desiredFont = { _actualFont };
// set TSF Foreground
@ -1678,7 +1679,8 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// Make sure we have a non-zero font size
const auto newSize = std::max<short>(gsl::narrow_cast<short>(fontSize), 1);
const auto fontFace = _settings.FontFace();
_actualFont = { fontFace, 0, 10, { 0, newSize }, CP_UTF8, false };
const auto fontWeight = _settings.FontWeight();
_actualFont = { fontFace, 0, fontWeight.Weight, { 0, newSize }, CP_UTF8, false };
_desiredFont = { _actualFont };
auto lock = _terminal->LockForWriting();
@ -2197,13 +2199,14 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
// Initialize our font information.
const auto fontFace = settings.FontFace();
const short fontHeight = gsl::narrow_cast<short>(settings.FontSize());
const auto fontWeight = settings.FontWeight();
// The font width doesn't terribly matter, we'll only be using the
// height to look it up
// The other params here also largely don't matter.
// The family is only used to determine if the font is truetype or
// not, but DX doesn't use that info at all.
// The Codepage is additionally not actually used by the DX engine at all.
FontInfo actualFont = { fontFace, 0, 10, { 0, fontHeight }, CP_UTF8, false };
FontInfo actualFont = { fontFace, 0, fontWeight.Weight, { 0, fontHeight }, CP_UTF8, false };
FontInfoDesired desiredFont = { actualFont };
// If the settings have negative or zero row or column counts, ignore those counts.
@ -2497,6 +2500,9 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
eventArgs.FontSize(CharacterDimensions());
eventArgs.FontFace(_actualFont.GetFaceName());
::winrt::Windows::UI::Text::FontWeight weight;
weight.Weight = static_cast<uint16_t>(_actualFont.GetWeight());
eventArgs.FontWeight(weight);
}
// Method Description:

View file

@ -34,6 +34,7 @@ namespace Microsoft.Terminal.Settings
String FontFace;
Int32 FontSize;
Windows.UI.Text.FontWeight FontWeight;
String Padding;
IKeyBindings KeyBindings;

View file

@ -34,6 +34,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_padding{ DEFAULT_PADDING },
_fontFace{ DEFAULT_FONT_FACE },
_fontSize{ DEFAULT_FONT_SIZE },
_fontWeight{ DEFAULT_FONT_WEIGHT },
_backgroundImage{},
_backgroundImageOpacity{ 1.0 },
_backgroundImageStretchMode{ winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill },
@ -258,6 +259,16 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
_fontSize = value;
}
winrt::Windows::UI::Text::FontWeight TerminalSettings::FontWeight() noexcept
{
return _fontWeight;
}
void TerminalSettings::FontWeight(winrt::Windows::UI::Text::FontWeight value) noexcept
{
_fontWeight = value;
}
void TerminalSettings::BackgroundImage(hstring const& value)
{
_backgroundImage = value;

View file

@ -68,6 +68,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
void FontFace(hstring const& value);
int32_t FontSize() noexcept;
void FontSize(int32_t value) noexcept;
winrt::Windows::UI::Text::FontWeight FontWeight() noexcept;
void FontWeight(winrt::Windows::UI::Text::FontWeight value) noexcept;
hstring BackgroundImage();
void BackgroundImage(hstring const& value);
@ -133,6 +135,7 @@ namespace winrt::Microsoft::Terminal::Settings::implementation
double _tintOpacity;
hstring _fontFace;
int32_t _fontSize;
winrt::Windows::UI::Text::FontWeight _fontWeight;
hstring _padding;
hstring _backgroundImage;
double _backgroundImageOpacity;

View file

@ -30,6 +30,7 @@ constexpr short DEFAULT_HISTORY_SIZE = 9001;
// TODO GH 2674, don't disable this warning, move to std::wstring_view or something like that.
const std::wstring DEFAULT_FONT_FACE{ L"Cascadia Mono" };
constexpr int DEFAULT_FONT_SIZE = 12;
constexpr uint16_t DEFAULT_FONT_WEIGHT = 400; // normal
constexpr int DEFAULT_ROWS = 30;
constexpr int DEFAULT_COLS = 120;

View file

@ -2003,7 +2003,7 @@ CATCH_RETURN();
try
{
std::wstring fontName(desired.GetFaceName());
DWRITE_FONT_WEIGHT weight = DWRITE_FONT_WEIGHT_NORMAL;
DWRITE_FONT_WEIGHT weight = static_cast<DWRITE_FONT_WEIGHT>(desired.GetWeight());
DWRITE_FONT_STYLE style = DWRITE_FONT_STYLE_NORMAL;
DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
std::wstring localeName = _GetLocaleName();