terminal/src/terminal/adapter/terminalOutput.hpp
James Holderness 90ff261c35
Add support for downloadable soft fonts (#10011)
This PR adds conhost support for downloadable soft fonts - also known as
dynamically redefinable character sets (DRCS) - using the `DECDLD`
escape sequence.

These fonts are typically designed to work on a specific terminal model,
and each model tends to have a different character cell size. So in
order to support as many models as possible, the code attempts to detect
the original target size of the font, and then scale the glyphs to fit
our current cell size.

Once a font has been downloaded to the terminal, it can be designated in
the same way you would a standard character set, using an `SCS` escape
sequence. The identification string for the set is defined by the
`DECDLD` sequence. Internally we map the characters in this set to code
points `U+EF20` to `U+EF7F` in the Unicode private use are (PUA).

Then in the renderer, any characters in that range are split off into
separate runs, which get painted with a special font. The font itself is
dynamically generated as an in-memory resource, constructed from the
downloaded character bitmaps which have been scaled to the appropriate
size.

If no soft fonts are in use, then no mapping of the PUA code points will
take place, so this shouldn't interfere with anyone using those code
points for something else, as along as they aren't also trying to use
soft fonts. I also tried to pick a PUA range that hadn't already been
snatched up by Nerd Fonts, but if we do receive reports of a conflict,
it's easy enough to change.

## Validation Steps Performed

I added an adapter test that runs through a bunch of parameter
variations for the `DECDLD` sequence, to make sure we're correctly
detecting the font sizes for most of the known DEC terminal models.

I've also tested manually on a wide range of existing fonts, of varying
dimensions, and from multiple sources, and made sure they all worked
reasonably well.

Closes #9164
2021-08-06 20:41:02 +00:00

56 lines
2 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- terminalOutput.hpp
Abstract:
- Provides a set of functions for translating certain characters into other
characters. There are special VT modes where the display characters (values
x20 - x7f) should be displayed as other characters. This module provides an
componentization of that logic.
Author(s):
- Mike Griese (migrie) 03-Mar-2016
--*/
#pragma once
#include "termDispatch.hpp"
namespace Microsoft::Console::VirtualTerminal
{
class TerminalOutput sealed
{
public:
TerminalOutput() noexcept;
wchar_t TranslateKey(const wchar_t wch) const noexcept;
bool Designate94Charset(const size_t gsetNumber, const VTID charset);
bool Designate96Charset(const size_t gsetNumber, const VTID charset);
void SetDrcs94Designation(const VTID charset);
void SetDrcs96Designation(const VTID charset);
bool LockingShift(const size_t gsetNumber);
bool LockingShiftRight(const size_t gsetNumber);
bool SingleShift(const size_t gsetNumber);
bool NeedToTranslate() const noexcept;
void EnableGrTranslation(boolean enabled);
private:
const std::wstring_view _LookupTranslationTable94(const VTID charset) const;
const std::wstring_view _LookupTranslationTable96(const VTID charset) const;
bool _SetTranslationTable(const size_t gsetNumber, const std::wstring_view translationTable);
void _ReplaceDrcsTable(const std::wstring_view oldTable, const std::wstring_view newTable);
std::array<std::wstring_view, 4> _gsetTranslationTables;
size_t _glSetNumber = 0;
size_t _grSetNumber = 2;
std::wstring_view _glTranslationTable;
std::wstring_view _grTranslationTable;
mutable std::wstring_view _ssTranslationTable;
boolean _grTranslationEnabled = false;
VTID _drcsId = 0;
std::wstring_view _drcsTranslationTable;
};
}