Compare commits
2 commits
main
...
dev/lhecke
Author | SHA1 | Date | |
---|---|---|---|
ebbc14c113 | |||
70eeea68e4 |
33
NOTICE.md
33
NOTICE.md
|
@ -117,7 +117,6 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
```
|
||||
|
||||
## dynamic_bitset
|
||||
|
@ -148,7 +147,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
## \{fmt\}
|
||||
|
@ -215,10 +213,8 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
|
||||
## boost
|
||||
|
||||
**Source**: [https://github.com/boostorg/boost](https://github.com/boostorg/boost)
|
||||
|
@ -249,7 +245,36 @@ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
|||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
```
|
||||
|
||||
## robin-hood-hashing
|
||||
|
||||
**Source**: [https://github.com/martinus/robin-hood-hashing](https://github.com/martinus/robin-hood-hashing)
|
||||
|
||||
### License
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021 Martin Ankerl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
## ConEmu
|
||||
|
|
|
@ -400,6 +400,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsTerminal.UIA.Tests",
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "api-ms-win-core-synch-l1-2-0", "src\api-ms-win-core-synch-l1-2-0\api-ms-win-core-synch-l1-2-0.vcxproj", "{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RendererAtlas", "src\renderer\atlas\atlas.vcxproj", "{8222900C-8B6C-452A-91AC-BE95DB04B95F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
AuditMode|Any CPU = AuditMode|Any CPU
|
||||
|
@ -3339,6 +3341,46 @@ Global
|
|||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x64.Build.0 = Release|x64
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5}.Release|x86.Build.0 = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|Any CPU.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x64Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|DotNet_x86Test.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.ActiveCfg = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x64.Build.0 = AuditMode|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.ActiveCfg = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.AuditMode|x86.Build.0 = AuditMode|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x64Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|DotNet_x86Test.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x64.Build.0 = Debug|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|Any CPU.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|ARM64.Build.0 = Fuzzing|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|DotNet_x86Test.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.ActiveCfg = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x64.Build.0 = Fuzzing|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Fuzzing|x86.Build.0 = Fuzzing|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x64Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|DotNet_x86Test.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.ActiveCfg = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x64.Build.0 = Release|x64
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -3438,6 +3480,9 @@ Global
|
|||
{C323DAEE-B307-4C7B-ACE5-7293CBEFCB5B} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{F19DACD5-0C6E-40DC-B6E4-767A3200542C} = {BDB237B6-1D1D-400F-84CC-40A58FA59C8E}
|
||||
{9CF74355-F018-4C19-81AD-9DC6B7F2C6F5} = {89CDCC5C-9F53-4054-97A4-639D99F169CD}
|
||||
{8222900C-8B6C-452A-91AC-BE95DB04B95F} = {05500DEF-2294-41E3-AF9A-24E580B82836}
|
||||
{44D35904-4DC6-4EEC-86F2-6E3E341C95BE} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
{B321ECD6-18E2-4F07-BFB0-B63750CE0CBD} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3140B1B7-C8EE-43D1-A772-D82A7061A271}
|
||||
|
|
21
oss/robin-hood-hashing/LICENSE
Normal file
21
oss/robin-hood-hashing/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018-2021 Martin Ankerl
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
9
oss/robin-hood-hashing/MAINTAINER_README.md
Normal file
9
oss/robin-hood-hashing/MAINTAINER_README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
### Notes for Future Maintainers
|
||||
|
||||
The provenance information (where it came from and which commit) is stored in the file `cgmanifest.json` in the same directory as this readme.
|
||||
Please update the provenance information in that file when ingesting an updated version of the dependent library.
|
||||
That provenance file is automatically read and inventoried by Microsoft systems to ensure compliance with appropiate governance standards.
|
||||
|
||||
## Updates
|
||||
|
||||
Get updates from here: https://github.com/martinus/robin-hood-hashing
|
14
oss/robin-hood-hashing/cgmanifest.json
Normal file
14
oss/robin-hood-hashing/cgmanifest.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"Registrations": [
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"repositoryUrl": "https://github.com/martinus/robin-hood-hashing",
|
||||
"commitHash": "24b3f50f9532153edc23b29ae277dcccfd75a462"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"Version": 1
|
||||
}
|
2529
oss/robin-hood-hashing/robin_hood.h
Normal file
2529
oss/robin-hood-hashing/robin_hood.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -12,17 +12,27 @@
|
|||
void CharRowCellReference::operator=(const std::wstring_view chars)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, chars.empty());
|
||||
|
||||
auto& dbcsAttr = _cellData().DbcsAttr();
|
||||
|
||||
if (chars.size() == 1)
|
||||
{
|
||||
if (dbcsAttr.IsGlyphStored())
|
||||
{
|
||||
auto& storage = _parent.GetUnicodeStorage();
|
||||
const auto key = _parent.GetStorageKey(_index);
|
||||
storage.Erase(key);
|
||||
}
|
||||
|
||||
_cellData().Char() = chars.front();
|
||||
_cellData().DbcsAttr().SetGlyphStored(false);
|
||||
dbcsAttr.SetGlyphStored(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& storage = _parent.GetUnicodeStorage();
|
||||
const auto key = _parent.GetStorageKey(_index);
|
||||
storage.StoreGlyph(key, { chars.cbegin(), chars.cend() });
|
||||
_cellData().DbcsAttr().SetGlyphStored(true);
|
||||
storage.StoreGlyph(key, chars);
|
||||
dbcsAttr.SetGlyphStored(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,30 +117,3 @@ CharRowCellReference::const_iterator CharRowCellReference::end() const
|
|||
}
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
bool operator==(const CharRowCellReference& ref, const std::vector<wchar_t>& glyph)
|
||||
{
|
||||
const DbcsAttribute& dbcsAttr = ref._cellData().DbcsAttr();
|
||||
if (glyph.size() == 1 && dbcsAttr.IsGlyphStored())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (glyph.size() > 1 && !dbcsAttr.IsGlyphStored())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (glyph.size() == 1 && !dbcsAttr.IsGlyphStored())
|
||||
{
|
||||
return ref._cellData().Char() == glyph.front();
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& chars = ref._parent.GetUnicodeStorage().GetText(ref._parent.GetStorageKey(ref._index));
|
||||
return chars == glyph;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const std::vector<wchar_t>& glyph, const CharRowCellReference& ref)
|
||||
{
|
||||
return ref == glyph;
|
||||
}
|
||||
|
|
|
@ -44,9 +44,6 @@ public:
|
|||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
|
||||
friend bool operator==(const CharRowCellReference& ref, const std::vector<wchar_t>& glyph);
|
||||
friend bool operator==(const std::vector<wchar_t>& glyph, const CharRowCellReference& ref);
|
||||
|
||||
private:
|
||||
// what char row the object belongs to
|
||||
CharRow& _parent;
|
||||
|
@ -58,6 +55,3 @@ private:
|
|||
|
||||
std::wstring_view _glyphData() const;
|
||||
};
|
||||
|
||||
bool operator==(const CharRowCellReference& ref, const std::vector<wchar_t>& glyph);
|
||||
bool operator==(const std::vector<wchar_t>& glyph, const CharRowCellReference& ref);
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
#include "precomp.h"
|
||||
#include "UnicodeStorage.hpp"
|
||||
|
||||
UnicodeStorage::UnicodeStorage() noexcept :
|
||||
_map{}
|
||||
{
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - fetches the text associated with key
|
||||
// Arguments:
|
||||
|
@ -16,26 +11,30 @@ UnicodeStorage::UnicodeStorage() noexcept :
|
|||
// Return Value:
|
||||
// - the glyph data associated with key
|
||||
// Note: will throw exception if key is not stored yet
|
||||
const UnicodeStorage::mapped_type& UnicodeStorage::GetText(const key_type key) const
|
||||
std::wstring_view UnicodeStorage::GetText(const COORD key) const
|
||||
{
|
||||
return _map.at(key);
|
||||
return { _map.at(key).data(), 2 };
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - stores glyph data associated with key.
|
||||
// - stores a surrogate pair associated with key.
|
||||
// Arguments:
|
||||
// - key - the key into the storage
|
||||
// - glyph - the glyph data to store
|
||||
void UnicodeStorage::StoreGlyph(const key_type key, const mapped_type& glyph)
|
||||
void UnicodeStorage::StoreGlyph(const COORD key, const std::wstring_view& glyph)
|
||||
{
|
||||
_map.insert_or_assign(key, glyph);
|
||||
// If you crash here it means that Windows Terminal has started supporting more of unicode.
|
||||
// At the time of writing it only supports surrogate pairs at most.
|
||||
// Replace the _map value type with std::wstring or something (at the cost of reduced performance).
|
||||
assert(glyph.size() == 2);
|
||||
memcpy(_map[key].data(), glyph.data(), 2 * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - erases key and its associated data from the storage
|
||||
// Arguments:
|
||||
// - key - the key to remove
|
||||
void UnicodeStorage::Erase(const key_type key) noexcept
|
||||
void UnicodeStorage::Erase(const COORD key) noexcept
|
||||
{
|
||||
_map.erase(key);
|
||||
}
|
||||
|
@ -50,7 +49,8 @@ void UnicodeStorage::Erase(const key_type key) noexcept
|
|||
void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width)
|
||||
{
|
||||
// Make a temporary map to hold all the new row positioning
|
||||
std::unordered_map<key_type, mapped_type> newMap;
|
||||
decltype(_map) newMap;
|
||||
newMap.reserve(_map.size());
|
||||
|
||||
// Walk through every stored item.
|
||||
for (const auto& pair : _map)
|
||||
|
@ -94,5 +94,5 @@ void UnicodeStorage::Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const
|
|||
}
|
||||
|
||||
// Swap into the stored map, free the temporary when we exit.
|
||||
_map.swap(newMap);
|
||||
_map = std::move(newMap);
|
||||
}
|
||||
|
|
|
@ -14,29 +14,16 @@ Author(s):
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <climits>
|
||||
|
||||
// std::unordered_map needs help to know how to hash a COORD
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
struct hash<COORD>
|
||||
{
|
||||
// Routine Description:
|
||||
// - hashes a coord. coord will be hashed by storing the x and y values consecutively in the lower
|
||||
// bits of a size_t.
|
||||
// Arguments:
|
||||
// - coord - the coord to hash
|
||||
// Return Value:
|
||||
// - the hashed coord
|
||||
constexpr size_t operator()(const COORD& coord) const noexcept
|
||||
// We take COORD by value not just because it neatly fits into a register...
|
||||
// Reading unaligned pointers doesn't work
|
||||
size_t operator()(COORD coord) const noexcept
|
||||
{
|
||||
size_t retVal = coord.Y;
|
||||
const size_t xCoord = coord.X;
|
||||
retVal |= xCoord << (sizeof(coord.Y) * CHAR_BIT);
|
||||
return retVal;
|
||||
return std::hash<uint32_t>{}(til::bit_cast<uint32_t>(coord));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -44,21 +31,13 @@ namespace std
|
|||
class UnicodeStorage final
|
||||
{
|
||||
public:
|
||||
using key_type = typename COORD;
|
||||
using mapped_type = typename std::vector<wchar_t>;
|
||||
|
||||
UnicodeStorage() noexcept;
|
||||
|
||||
const mapped_type& GetText(const key_type key) const;
|
||||
|
||||
void StoreGlyph(const key_type key, const mapped_type& glyph);
|
||||
|
||||
void Erase(const key_type key) noexcept;
|
||||
|
||||
std::wstring_view GetText(const COORD key) const;
|
||||
void StoreGlyph(const COORD key, const std::wstring_view& glyph);
|
||||
void Erase(const COORD key) noexcept;
|
||||
void Remap(const std::unordered_map<SHORT, SHORT>& rowMap, const std::optional<SHORT> width);
|
||||
|
||||
private:
|
||||
std::unordered_map<key_type, mapped_type> _map;
|
||||
std::unordered_map<COORD, std::array<wchar_t, 2>> _map;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
friend class UnicodeStorageTests;
|
||||
|
|
|
@ -19,8 +19,8 @@ class UnicodeStorageTests
|
|||
{
|
||||
UnicodeStorage storage;
|
||||
const COORD coord{ 1, 3 };
|
||||
const std::vector<wchar_t> newMoon{ 0xD83C, 0xDF11 };
|
||||
const std::vector<wchar_t> fullMoon{ 0xD83C, 0xDF15 };
|
||||
const std::wstring newMoon{ L"\uD83C\uDF11" };
|
||||
const std::wstring fullMoon{ L"\uD83C\uDF15" };
|
||||
|
||||
// store initial glyph
|
||||
storage.StoreGlyph(coord, newMoon);
|
||||
|
@ -28,7 +28,7 @@ class UnicodeStorageTests
|
|||
// verify it was stored
|
||||
auto findIt = storage._map.find(coord);
|
||||
VERIFY_ARE_NOT_EQUAL(findIt, storage._map.end());
|
||||
const std::vector<wchar_t>& newMoonGlyph = findIt->second;
|
||||
const auto& newMoonGlyph = findIt->second;
|
||||
VERIFY_ARE_EQUAL(newMoonGlyph.size(), newMoon.size());
|
||||
for (size_t i = 0; i < newMoon.size(); ++i)
|
||||
{
|
||||
|
@ -41,7 +41,7 @@ class UnicodeStorageTests
|
|||
// verify the glyph was overwritten
|
||||
findIt = storage._map.find(coord);
|
||||
VERIFY_ARE_NOT_EQUAL(findIt, storage._map.end());
|
||||
const std::vector<wchar_t>& fullMoonGlyph = findIt->second;
|
||||
const auto& fullMoonGlyph = findIt->second;
|
||||
VERIFY_ARE_EQUAL(fullMoonGlyph.size(), fullMoon.size());
|
||||
for (size_t i = 0; i < fullMoon.size(); ++i)
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\dep\Win32K;$(SolutionDir)\oss\boost\boost_1_73_0;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\interval_tree;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\pcg\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)\src\inc;$(SolutionDir)\dep;$(SolutionDir)\dep\Console;$(SolutionDir)\dep\gsl\include;$(SolutionDir)\dep\wil\include;$(SolutionDir)\dep\Win32K;$(SolutionDir)\oss\boost\boost_1_73_0;$(SolutionDir)\oss\chromium;$(SolutionDir)\oss\dynamic_bitset;$(SolutionDir)\oss\fmt\include;$(SolutionDir)\oss\interval_tree;$(SolutionDir)\oss\libpopcnt;$(SolutionDir)\oss\pcg\include;$(SolutionDir)\oss\robin-hood-hashing;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
|
|
|
@ -46,6 +46,9 @@
|
|||
<ProjectReference Include="..\..\renderer\dx\lib\dx.vcxproj">
|
||||
<Project>{48d21369-3d7b-4431-9967-24e81292cf62}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\renderer\atlas\atlas.vcxproj">
|
||||
<Project>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\renderer\gdi\lib\gdi.vcxproj">
|
||||
<Project>{1c959542-bac2-4e55-9a6d-13251914cbb9}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -274,8 +274,7 @@ void ApiRoutines::GetNumberOfConsoleMouseButtonsImpl(ULONG& buttons) noexcept
|
|||
const FontInfo& fontInfo = activeScreenInfo.GetCurrentFont();
|
||||
consoleFontInfoEx.FontFamily = fontInfo.GetFamily();
|
||||
consoleFontInfoEx.FontWeight = fontInfo.GetWeight();
|
||||
|
||||
RETURN_IF_FAILED(fontInfo.FillLegacyNameBuffer(gsl::make_span(consoleFontInfoEx.FaceName)));
|
||||
fontInfo.FillLegacyNameBuffer(consoleFontInfoEx.FaceName);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,7 @@ Revision History:
|
|||
#include "ConsoleArguments.hpp"
|
||||
#include "ApiRoutines.h"
|
||||
|
||||
#include "../renderer/inc/IRenderData.hpp"
|
||||
#include "../renderer/inc/IRenderEngine.hpp"
|
||||
#include "../renderer/inc/IRenderer.hpp"
|
||||
#include "../renderer/inc/IFontDefaultList.hpp"
|
||||
#include "../renderer/base/Renderer.hpp"
|
||||
|
||||
#include "../server/DeviceComm.h"
|
||||
#include "../server/ConDrvDeviceComm.h"
|
||||
|
@ -62,7 +59,7 @@ public:
|
|||
|
||||
std::vector<wchar_t> WordDelimiters;
|
||||
|
||||
Microsoft::Console::Render::IRenderer* pRender;
|
||||
Microsoft::Console::Render::Renderer* pRender;
|
||||
|
||||
Microsoft::Console::Render::IFontDefaultList* pFontDefaultList;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ Settings::Settings() :
|
|||
_fInterceptCopyPaste(0),
|
||||
_DefaultForeground(INVALID_COLOR),
|
||||
_DefaultBackground(INVALID_COLOR),
|
||||
_fUseDx(false),
|
||||
_fUseDx(0),
|
||||
_fCopyColor(false)
|
||||
{
|
||||
_dwScreenBufferSize.X = 80;
|
||||
|
@ -816,7 +816,7 @@ void Settings::SetTerminalScrolling(const bool terminalScrollingEnabled) noexcep
|
|||
// - This is based on user preference and velocity hold back state.
|
||||
// Return Value:
|
||||
// - True means use DirectX renderer. False means use GDI renderer.
|
||||
bool Settings::GetUseDx() const noexcept
|
||||
DWORD Settings::GetUseDx() const noexcept
|
||||
{
|
||||
return _fUseDx;
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ public:
|
|||
bool IsTerminalScrolling() const noexcept;
|
||||
void SetTerminalScrolling(const bool terminalScrollingEnabled) noexcept;
|
||||
|
||||
bool GetUseDx() const noexcept;
|
||||
DWORD GetUseDx() const noexcept;
|
||||
bool GetCopyColor() const noexcept;
|
||||
|
||||
private:
|
||||
|
@ -230,7 +230,7 @@ private:
|
|||
bool _fAutoReturnOnNewline;
|
||||
bool _fRenderGridWorldwide;
|
||||
bool _fScreenReversed;
|
||||
bool _fUseDx;
|
||||
DWORD _fUseDx;
|
||||
bool _fCopyColor;
|
||||
|
||||
std::array<COLORREF, XTERM_COLOR_TABLE_SIZE> _colorTable;
|
||||
|
|
|
@ -771,8 +771,9 @@ PWSTR TranslateConsoleTitle(_In_ PCWSTR pwszConsoleTitle, const BOOL fUnexpand,
|
|||
|
||||
// Set up the renderer to be used to calculate the width of a glyph,
|
||||
// should we be unable to figure out its width another way.
|
||||
auto pfn = std::bind(&Renderer::IsGlyphWideByFont, static_cast<Renderer*>(g.pRender), std::placeholders::_1);
|
||||
SetGlyphWidthFallback(pfn);
|
||||
SetGlyphWidthFallback([renderer = g.pRender](const std::wstring_view& glyph) -> bool {
|
||||
return renderer->IsGlyphWideByFont(glyph);
|
||||
});
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ class CodepointWidthDetectorTests
|
|||
}
|
||||
}
|
||||
|
||||
static bool FallbackMethod(const std::wstring_view glyph)
|
||||
static bool FallbackMethod(const std::wstring_view& glyph)
|
||||
{
|
||||
if (glyph.size() < 1)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,15 @@
|
|||
|
||||
namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
{
|
||||
template<class To, class From, std::enable_if_t<std::conjunction_v<std::bool_constant<sizeof(To) == sizeof(From)>, std::is_trivially_copyable<To>, std::is_trivially_copyable<From>>, int> = 0>
|
||||
[[nodiscard]] constexpr To bit_cast(const From& _Val) noexcept
|
||||
{
|
||||
#ifdef __cpp_lib_bit_cast
|
||||
#warning "Replace til::bit_cast and __builtin_bit_cast with std::bit_cast"
|
||||
#endif
|
||||
return __builtin_bit_cast(To, _Val);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void manage_vector(std::vector<T>& vector, typename std::vector<T>::size_type requestedSize, float shrinkThreshold)
|
||||
{
|
||||
|
|
60
src/inc/til/pair.h
Normal file
60
src/inc/til/pair.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
||||
{
|
||||
// pair is a simple clone of std::pair, with one difference:
|
||||
// copy and move constructors and operators are explicitly defaulted.
|
||||
// This allows pair to be std::is_trivially_copyable, if both T and S are.
|
||||
// --> pair can be used with memcpy(), unlike std::pair.
|
||||
template<typename T, typename S>
|
||||
struct pair
|
||||
{
|
||||
using first_type = T;
|
||||
using second_type = S;
|
||||
|
||||
pair() = default;
|
||||
|
||||
pair(const pair&) = default;
|
||||
pair& operator=(const pair&) = default;
|
||||
|
||||
pair(pair&&) = default;
|
||||
pair& operator=(pair&&) = default;
|
||||
|
||||
constexpr pair(const T& first, const S& second) noexcept(std::is_nothrow_copy_constructible_v<T>&& std::is_nothrow_copy_constructible_v<S>) :
|
||||
first(first), second(second)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr pair(T&& first, S&& second) noexcept(std::is_nothrow_constructible_v<T>&& std::is_nothrow_constructible_v<S>) :
|
||||
first(std::forward<T>(first)), second(std::forward<S>(second))
|
||||
{
|
||||
}
|
||||
|
||||
constexpr void swap(pair& other) noexcept(std::is_nothrow_swappable_v<T>&& std::is_nothrow_swappable_v<S>)
|
||||
{
|
||||
if (this != std::addressof(other))
|
||||
{
|
||||
std::swap(first, other.first);
|
||||
std::swap(second, other.second);
|
||||
}
|
||||
}
|
||||
|
||||
first_type first{};
|
||||
second_type second{};
|
||||
};
|
||||
|
||||
template<typename T, typename S>
|
||||
[[nodiscard]] constexpr bool operator==(const pair<T, S>& lhs, const pair<T, S>& rhs)
|
||||
{
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
|
||||
template<typename T, typename S>
|
||||
[[nodiscard]] constexpr bool operator!=(const pair<T, S>& lhs, const pair<T, S>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
|
@ -9,17 +9,14 @@
|
|||
#include "window.hpp"
|
||||
#include "windowio.hpp"
|
||||
#include "windowdpiapi.hpp"
|
||||
#include "windowmetrics.hpp"
|
||||
#include "WindowMetrics.hpp"
|
||||
|
||||
#include "../../inc/conint.h"
|
||||
|
||||
#include "../../host/globals.h"
|
||||
#include "../../host/dbcs.h"
|
||||
#include "../../host/getset.h"
|
||||
#include "../../host/misc.h"
|
||||
#include "../../host/_output.h"
|
||||
#include "../../host/output.h"
|
||||
#include "../../host/renderData.hpp"
|
||||
#include "../../host/scrolling.hpp"
|
||||
#include "../../host/srvinit.h"
|
||||
#include "../../host/stream.h"
|
||||
|
@ -30,6 +27,7 @@
|
|||
#include "../../renderer/gdi/gdirenderer.hpp"
|
||||
|
||||
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
|
||||
#include "../../renderer/atlas/AtlasEngine.h"
|
||||
#include "../../renderer/dx/DxRenderer.hpp"
|
||||
#endif
|
||||
|
||||
|
@ -209,16 +207,18 @@ void Window::_UpdateSystemMetrics() const
|
|||
// Ensure we have appropriate system metrics before we start constructing the window.
|
||||
_UpdateSystemMetrics();
|
||||
|
||||
const bool useDx = pSettings->GetUseDx();
|
||||
const auto useDx = pSettings->GetUseDx();
|
||||
GdiEngine* pGdiEngine = nullptr;
|
||||
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
|
||||
[[maybe_unused]] DxEngine* pDxEngine = nullptr;
|
||||
DxEngine* pDxEngine = nullptr;
|
||||
AtlasEngine* pAtlasEngine = nullptr;
|
||||
#endif
|
||||
try
|
||||
{
|
||||
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
|
||||
if (useDx)
|
||||
switch (useDx)
|
||||
{
|
||||
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
|
||||
case 1:
|
||||
pDxEngine = new DxEngine();
|
||||
// TODO: MSFT:21255595 make this less gross
|
||||
// Manually set the Dx Engine to Hwnd mode. When we're trying to
|
||||
|
@ -227,12 +227,16 @@ void Window::_UpdateSystemMetrics() const
|
|||
// math in the hwnd mode, not the Composition mode.
|
||||
THROW_IF_FAILED(pDxEngine->SetHwnd(nullptr));
|
||||
g.pRender->AddRenderEngine(pDxEngine);
|
||||
}
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
pAtlasEngine = new AtlasEngine();
|
||||
g.pRender->AddRenderEngine(pAtlasEngine);
|
||||
break;
|
||||
#endif
|
||||
{
|
||||
default:
|
||||
pGdiEngine = new GdiEngine();
|
||||
g.pRender->AddRenderEngine(pGdiEngine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
|
@ -242,10 +246,6 @@ void Window::_UpdateSystemMetrics() const
|
|||
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
SCREEN_INFORMATION& siAttached = GetScreenInfo();
|
||||
|
||||
siAttached.RefreshFontWithRenderer();
|
||||
|
||||
// Save reference to settings
|
||||
_pSettings = pSettings;
|
||||
|
||||
|
@ -324,7 +324,7 @@ void Window::_UpdateSystemMetrics() const
|
|||
_hWnd = hWnd;
|
||||
|
||||
#if TIL_FEATURE_CONHOSTDXENGINE_ENABLED
|
||||
if (useDx)
|
||||
if (pDxEngine)
|
||||
{
|
||||
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->SetHwnd(hWnd))));
|
||||
|
||||
|
@ -333,6 +333,10 @@ void Window::_UpdateSystemMetrics() const
|
|||
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pDxEngine->Enable())));
|
||||
}
|
||||
}
|
||||
else if (pAtlasEngine)
|
||||
{
|
||||
status = NTSTATUS_FROM_WIN32(HRESULT_CODE((pAtlasEngine->SetHwnd(hWnd))));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
@ -362,6 +366,7 @@ void Window::_UpdateSystemMetrics() const
|
|||
// Post a window size update so that the new console window will size itself correctly once it's up and
|
||||
// running. This works around chicken & egg cases involving window size calculations having to do with font
|
||||
// sizes, DPI, and non-primary monitors (see MSFT #2367234).
|
||||
SCREEN_INFORMATION& siAttached = GetScreenInfo();
|
||||
siAttached.PostUpdateWindowSize();
|
||||
|
||||
// Locate window theming modules and try to set the dark mode.
|
||||
|
|
|
@ -63,7 +63,7 @@ const RegistrySerialization::_RegPropertyMap RegistrySerialization::s_PropertyMa
|
|||
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTFOREGROUND, SET_FIELD_AND_SIZE(_DefaultForeground) },
|
||||
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_DEFAULTBACKGROUND, SET_FIELD_AND_SIZE(_DefaultBackground) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_TERMINALSCROLLING, SET_FIELD_AND_SIZE(_TerminalScrolling) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
|
||||
{ _RegPropertyType::Dword, CONSOLE_REGISTRY_USEDX, SET_FIELD_AND_SIZE(_fUseDx) },
|
||||
{ _RegPropertyType::Boolean, CONSOLE_REGISTRY_COPYCOLOR, SET_FIELD_AND_SIZE(_fCopyColor) }
|
||||
|
||||
};
|
||||
|
@ -251,7 +251,8 @@ NTSTATUS RegistrySerialization::s_OpenKey(_In_opt_ HKEY const hKey, _In_ PCWSTR
|
|||
[[nodiscard]]
|
||||
NTSTATUS RegistrySerialization::s_DeleteValue(const HKEY hKey, _In_ PCWSTR const pwszValueName)
|
||||
{
|
||||
return NTSTATUS_FROM_WIN32(RegDeleteKeyValueW(hKey, nullptr, pwszValueName));
|
||||
const auto result = RegDeleteKeyValueW(hKey, nullptr, pwszValueName);
|
||||
return result == ERROR_FILE_NOT_FOUND ? S_OK : NTSTATUS_FROM_WIN32(result);
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
|
1128
src/renderer/atlas/AtlasEngine.cpp
Normal file
1128
src/renderer/atlas/AtlasEngine.cpp
Normal file
File diff suppressed because it is too large
Load diff
344
src/renderer/atlas/AtlasEngine.h
Normal file
344
src/renderer/atlas/AtlasEngine.h
Normal file
|
@ -0,0 +1,344 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <d2d1.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dwrite.h>
|
||||
#include <dxgi.h>
|
||||
|
||||
#include <robin_hood.h>
|
||||
#include <til/pair.h>
|
||||
|
||||
#include "../../renderer/inc/IRenderEngine.hpp"
|
||||
|
||||
namespace Microsoft::Console::Render
|
||||
{
|
||||
class AtlasEngine final : public IRenderEngine
|
||||
{
|
||||
public:
|
||||
explicit AtlasEngine();
|
||||
|
||||
AtlasEngine(const AtlasEngine&) = delete;
|
||||
AtlasEngine& operator=(const AtlasEngine&) = delete;
|
||||
|
||||
// IRenderEngine
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
[[nodiscard]] HRESULT EndPaint() noexcept override;
|
||||
[[nodiscard]] bool RequiresContinuousRedraw() noexcept override;
|
||||
void WaitUntilCanRender() noexcept override;
|
||||
[[nodiscard]] HRESULT Present() noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
|
||||
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateSelection(const std::vector<SMALL_RECT>& rectangles) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept override;
|
||||
[[nodiscard]] HRESULT ResetLineTransform() noexcept override;
|
||||
[[nodiscard]] HRESULT PrepareLineTransform(const LineRendition lineRendition, const size_t targetRow, const size_t viewportLeft) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBackground() noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLineSet lines, const COLORREF color, const size_t cchLine, const COORD coordTarget) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const SIZE cellSize, const size_t centeringHint) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override;
|
||||
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept override;
|
||||
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
|
||||
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
|
||||
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept override;
|
||||
|
||||
// Just for compatibility with DxEngine, but can be removed at some point.
|
||||
HRESULT Enable()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// DxRenderer - getter
|
||||
[[nodiscard]] bool GetRetroTerminalEffect() const noexcept;
|
||||
[[nodiscard]] float GetScaling() const noexcept;
|
||||
[[nodiscard]] HANDLE GetSwapChainHandle();
|
||||
[[nodiscard]] Types::Viewport GetViewportInCharacters(const Types::Viewport& viewInPixels) const noexcept;
|
||||
[[nodiscard]] Types::Viewport GetViewportInPixels(const Types::Viewport& viewInCharacters) const noexcept;
|
||||
// DxRenderer - setter
|
||||
void SetAntialiasingMode(const D2D1_TEXT_ANTIALIAS_MODE antialiasingMode) noexcept;
|
||||
void SetCallback(std::function<void()> pfn);
|
||||
void SetDefaultTextBackgroundOpacity(const float opacity) noexcept;
|
||||
void SetForceFullRepaintRendering(bool enable) noexcept;
|
||||
[[nodiscard]] HRESULT SetHwnd(const HWND hwnd) noexcept;
|
||||
void SetPixelShaderPath(std::wstring_view value) noexcept;
|
||||
void SetRetroTerminalEffect(bool enable) noexcept;
|
||||
void SetSelectionBackground(const COLORREF color, const float alpha = 0.5f) noexcept;
|
||||
void SetSoftwareRendering(bool enable) noexcept;
|
||||
void SetWarningCallback(std::function<void(const HRESULT)> pfn);
|
||||
[[nodiscard]] HRESULT SetWindowSize(const SIZE pixels) noexcept;
|
||||
void ToggleShaderEffects();
|
||||
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& pfiFontInfoDesired, FontInfo& fiFontInfo, const std::unordered_map<std::wstring_view, uint32_t>& features, const std::unordered_map<std::wstring_view, float>& axes) noexcept;
|
||||
void UpdateHyperlinkHoveredId(const uint16_t hoveredId) noexcept;
|
||||
|
||||
// Some helper classes for the implementation.
|
||||
// public because I don't want to sprinkle the code with friends.
|
||||
public:
|
||||
template<typename T>
|
||||
struct aligned_buffer
|
||||
{
|
||||
constexpr aligned_buffer() noexcept = default;
|
||||
|
||||
explicit aligned_buffer(size_t size, size_t alignment) :
|
||||
_data{ THROW_IF_NULL_ALLOC(static_cast<T*>(_aligned_malloc(size * sizeof(T), alignment))) },
|
||||
_size{ size }
|
||||
{
|
||||
}
|
||||
|
||||
~aligned_buffer()
|
||||
{
|
||||
_aligned_free(_data);
|
||||
}
|
||||
|
||||
aligned_buffer(aligned_buffer&& other) noexcept :
|
||||
_data{ std::exchange(other._data, nullptr) },
|
||||
_size{ std::exchange(other._size, 0) }
|
||||
{
|
||||
}
|
||||
|
||||
aligned_buffer& operator=(aligned_buffer&& other) noexcept
|
||||
{
|
||||
_aligned_free(_data);
|
||||
_data = std::exchange(other._data, nullptr);
|
||||
_size = std::exchange(other._size, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* data()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
size_t size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
private:
|
||||
T* _data = nullptr;
|
||||
size_t _size = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct vec2
|
||||
{
|
||||
T x{};
|
||||
T y{};
|
||||
|
||||
bool operator==(const vec2& other) const noexcept
|
||||
{
|
||||
return memcmp(this, &other, sizeof(vec2)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const vec2& other) const noexcept
|
||||
{
|
||||
return memcmp(this, &other, sizeof(vec2)) != 0;
|
||||
}
|
||||
|
||||
vec2 operator*(const vec2& other) const noexcept
|
||||
{
|
||||
return { static_cast<T>(x * other.x), static_cast<T>(y * other.y) };
|
||||
}
|
||||
|
||||
vec2 operator/(const vec2& other) const noexcept
|
||||
{
|
||||
return { static_cast<T>(x / other.x), static_cast<T>(y / other.y) };
|
||||
}
|
||||
|
||||
template<typename U = T>
|
||||
U area() const noexcept
|
||||
{
|
||||
return static_cast<U>(x) * static_cast<U>(y);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct vec4
|
||||
{
|
||||
T x{};
|
||||
T y{};
|
||||
T z{};
|
||||
T w{};
|
||||
};
|
||||
|
||||
using u8 = uint8_t;
|
||||
using u16 = uint16_t;
|
||||
using u16x2 = vec2<u16>;
|
||||
using u32 = uint32_t;
|
||||
using u32x2 = vec2<u32>;
|
||||
using f32 = float;
|
||||
using f32x2 = vec2<f32>;
|
||||
using f32x4 = vec4<f32>;
|
||||
|
||||
union glyph_entry
|
||||
{
|
||||
uint32_t value;
|
||||
struct
|
||||
{
|
||||
uint32_t codepoint : 20;
|
||||
uint32_t wide : 1;
|
||||
uint32_t bold : 1;
|
||||
uint32_t italic : 1;
|
||||
};
|
||||
|
||||
constexpr bool operator==(const glyph_entry& other) const noexcept
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
};
|
||||
|
||||
struct glyph_entry_hasher
|
||||
{
|
||||
constexpr size_t operator()(glyph_entry entry) const noexcept
|
||||
{
|
||||
uint64_t x = entry.value;
|
||||
x ^= x >> 33;
|
||||
x *= UINT64_C(0xff51afd7ed558ccd);
|
||||
x ^= x >> 33;
|
||||
return static_cast<size_t>(x);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// D3D constant buffers sizes must be a multiple of 16 bytes.
|
||||
struct alignas(16) const_buffer
|
||||
{
|
||||
f32x4 viewport;
|
||||
u32x2 cellSize;
|
||||
u32 cellCountX;
|
||||
u32 backgroundColor;
|
||||
u32 selectionColor;
|
||||
#pragma warning(suppress : 4324) // structure was padded due to alignment specifier
|
||||
};
|
||||
|
||||
struct cell
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 glyphIndex;
|
||||
u16x2 glyphIndex16;
|
||||
};
|
||||
u32 flags;
|
||||
u32x2 color;
|
||||
};
|
||||
|
||||
enum class invalidation_flags : u8
|
||||
{
|
||||
none = 0,
|
||||
device = 1 << 0,
|
||||
size = 1 << 1,
|
||||
font = 1 << 2,
|
||||
cbuffer = 1 << 3,
|
||||
title = 1 << 4,
|
||||
};
|
||||
friend constexpr invalidation_flags operator~(invalidation_flags v) noexcept { return static_cast<invalidation_flags>(~static_cast<u8>(v)); }
|
||||
friend constexpr invalidation_flags operator|(invalidation_flags lhs, invalidation_flags rhs) noexcept { return static_cast<invalidation_flags>(static_cast<u8>(lhs) | static_cast<u8>(rhs)); }
|
||||
friend constexpr invalidation_flags operator&(invalidation_flags lhs, invalidation_flags rhs) noexcept { return static_cast<invalidation_flags>(static_cast<u8>(lhs) & static_cast<u8>(rhs)); }
|
||||
friend constexpr void operator|=(invalidation_flags& lhs, invalidation_flags rhs) noexcept { lhs = lhs | rhs; }
|
||||
friend constexpr void operator&=(invalidation_flags& lhs, invalidation_flags rhs) noexcept { lhs = lhs & rhs; }
|
||||
|
||||
// resource handling
|
||||
[[nodiscard]] HRESULT _handleException(const wil::ResultException& exception) noexcept;
|
||||
__declspec(noinline) void _createResources();
|
||||
__declspec(noinline) void _recreateSizeDependentResources();
|
||||
__declspec(noinline) void _recreateFontDependentResources();
|
||||
void _setShaderResources() const;
|
||||
void _updateConstantBuffer() const;
|
||||
|
||||
// text handling
|
||||
IDWriteTextFormat* _getTextFormat(bool bold, bool italic) const noexcept { return _r.textFormats[italic][bold].get(); }
|
||||
wil::com_ptr<IDWriteTextFormat> _createTextFormat(const wchar_t* fontFamilyName, DWRITE_FONT_WEIGHT fontWeight, DWRITE_FONT_STYLE fontStyle, float fontSize, const wchar_t* localeName) const;
|
||||
u16x2 _allocateAtlasCell() noexcept;
|
||||
void _drawGlyph(const til::pair<glyph_entry, std::array<u16x2, 2>>& pair) const;
|
||||
void _drawCursor() const;
|
||||
void _copyScratchpadCell(uint32_t scratchpadIndex, u16x2 target, uint32_t copyFlags = 0) const;
|
||||
|
||||
template<typename T1, typename T2>
|
||||
cell* _getCell(T1 x, T2 y) noexcept
|
||||
{
|
||||
return _r.cells.data() + static_cast<size_t>(_api.cellCount.x) * y + x;
|
||||
}
|
||||
|
||||
struct static_resources
|
||||
{
|
||||
wil::com_ptr<ID2D1Factory> d2dFactory;
|
||||
wil::com_ptr<IDWriteFactory> dwriteFactory;
|
||||
bool isWindows10OrGreater = true;
|
||||
} _sr;
|
||||
|
||||
struct resources
|
||||
{
|
||||
// D3D resources
|
||||
wil::com_ptr<ID3D11Device> device;
|
||||
wil::com_ptr<ID3D11DeviceContext1> deviceContext;
|
||||
wil::com_ptr<IDXGISwapChain1> swapChain;
|
||||
wil::unique_handle swapChainHandle;
|
||||
wil::unique_handle frameLatencyWaitableObject;
|
||||
wil::com_ptr<ID3D11RenderTargetView> renderTargetView;
|
||||
wil::com_ptr<ID3D11VertexShader> vertexShader;
|
||||
wil::com_ptr<ID3D11PixelShader> pixelShader;
|
||||
wil::com_ptr<ID3D11Buffer> constantBuffer;
|
||||
wil::com_ptr<ID3D11Buffer> cellBuffer;
|
||||
wil::com_ptr<ID3D11ShaderResourceView> cellView;
|
||||
|
||||
// D2D resources
|
||||
wil::com_ptr<ID3D11Texture2D> glyphBuffer;
|
||||
wil::com_ptr<ID3D11ShaderResourceView> glyphView;
|
||||
wil::com_ptr<ID3D11Texture2D> glyphScratchpad;
|
||||
wil::com_ptr<ID2D1RenderTarget> d2dRenderTarget;
|
||||
wil::com_ptr<ID2D1Brush> brush;
|
||||
wil::com_ptr<IDWriteTextFormat> textFormats[2][2];
|
||||
|
||||
// Resources dependent on _api.sizeInPixel
|
||||
aligned_buffer<cell> cells;
|
||||
// Resources dependent on _api.cellSize
|
||||
robin_hood::unordered_flat_map<glyph_entry, std::array<u16x2, 2>, glyph_entry_hasher> glyphs;
|
||||
std::vector<til::pair<glyph_entry, std::array<u16x2, 2>>> glyphQueue;
|
||||
u16x2 atlasSizeInPixel;
|
||||
u16x2 atlasPosition;
|
||||
} _r;
|
||||
|
||||
struct api_state
|
||||
{
|
||||
f32x2 cellSizeDIP; // invalidation_flags::font
|
||||
u16x2 cellSize; // invalidation_flags::size
|
||||
u16x2 cellCount; // caches `sizeInPixel / cellSize`
|
||||
u16x2 sizeInPixel; // invalidation_flags::size
|
||||
|
||||
std::wstring fontName; // invalidation_flags::font|size
|
||||
u16 fontSize = 0; // invalidation_flags::font|size
|
||||
u16 fontWeight = DWRITE_FONT_WEIGHT_NORMAL; // invalidation_flags::font
|
||||
u16 dpi = USER_DEFAULT_SCREEN_DPI; // invalidation_flags::font|size
|
||||
u16 antialiasingMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; // invalidation_flags::font
|
||||
|
||||
std::function<void()> swapChainChangedCallback;
|
||||
HWND hwnd = nullptr;
|
||||
} _api;
|
||||
|
||||
struct render_api_state
|
||||
{
|
||||
til::rectangle dirtyArea;
|
||||
u32x2 currentColor{};
|
||||
glyph_entry attributes{};
|
||||
u32 backgroundColor = ~u32(0);
|
||||
u32 selectionColor = 0x7fffffff;
|
||||
} _rapi;
|
||||
|
||||
invalidation_flags _invalidations = invalidation_flags::device;
|
||||
};
|
||||
}
|
49
src/renderer/atlas/atlas.vcxproj
Normal file
49
src/renderer/atlas/atlas.vcxproj
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{8222900C-8B6C-452A-91AC-BE95DB04B95F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>atlas</RootNamespace>
|
||||
<ProjectName>RendererAtlas</ProjectName>
|
||||
<TargetName>ConRenderAtlas</TargetName>
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.pre.props" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AtlasEngine.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="AtlasEngine.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<FxCompile Include="shader_ps.hlsl">
|
||||
<ShaderType>Pixel</ShaderType>
|
||||
<ShaderModel>4.1</ShaderModel>
|
||||
<VariableName>shader_ps</VariableName>
|
||||
<ObjectFileOutput />
|
||||
<HeaderFileOutput>$(OutDir)$(ProjectName)\%(Filename).h</HeaderFileOutput>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<AdditionalOptions Condition="'$(Configuration)'=='Release'">/Qstrip_debug /Qstrip_reflect %(AdditionalOptions)</AdditionalOptions>
|
||||
</FxCompile>
|
||||
<FxCompile Include="shader_vs.hlsl">
|
||||
<ShaderType>Vertex</ShaderType>
|
||||
<ShaderModel>4.1</ShaderModel>
|
||||
<VariableName>shader_vs</VariableName>
|
||||
<ObjectFileOutput />
|
||||
<HeaderFileOutput>$(OutDir)$(ProjectName)\%(Filename).h</HeaderFileOutput>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<AdditionalOptions Condition="'$(Configuration)'=='Release'">/Qstrip_debug /Qstrip_reflect %(AdditionalOptions)</AdditionalOptions>
|
||||
</FxCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(SolutionDir)src\common.build.post.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<AdditionalIncludeDirectories>$(OutDir)$(ProjectName)\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
4
src/renderer/atlas/pch.cpp
Normal file
4
src/renderer/atlas/pch.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#include "pch.h"
|
50
src/renderer/atlas/pch.h
Normal file
50
src/renderer/atlas/pch.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define NOMINMAX
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <d2d1.h>
|
||||
#include <d3d11_1.h>
|
||||
#include <dwrite.h>
|
||||
#include <dxgi1_3.h>
|
||||
#include <dxgidebug.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <gsl/pointers>
|
||||
#include <gsl/span>
|
||||
#include <gsl/gsl_util>
|
||||
#include <wil/com.h>
|
||||
#include <wil/result_macros.h>
|
||||
#include <wil/stl.h>
|
||||
#include <wil/win32_helpers.h>
|
||||
|
||||
#include <robin_hood.h>
|
||||
|
||||
// Dynamic Bitset (optional dependency on LibPopCnt for perf at bit counting)
|
||||
// Variable-size compressed-storage header-only bit flag storage library.
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
#include <dynamic_bitset.hpp>
|
||||
#pragma warning(pop)
|
||||
|
||||
// Chromium Numerics (safe math)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100) // '...': unreferenced formal parameter
|
||||
#pragma warning(disable : 26812) // The enum type '...' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
|
||||
#include <base/numerics/safe_math.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include "til.h"
|
||||
#include <til/pair.h>
|
75
src/renderer/atlas/shader_ps.hlsl
Normal file
75
src/renderer/atlas/shader_ps.hlsl
Normal file
|
@ -0,0 +1,75 @@
|
|||
// According to Nvidia's "Understanding Structured Buffer Performance" guide
|
||||
// one should aim for structures with sizes divisible by 128 bits (16 bytes).
|
||||
// This prevents elements from spanning cache lines.
|
||||
struct Cell
|
||||
{
|
||||
uint glyphPos;
|
||||
uint flags;
|
||||
uint2 color;
|
||||
};
|
||||
|
||||
cbuffer ConstantBuffer : register(b0)
|
||||
{
|
||||
float4 viewport;
|
||||
uint2 cellSize;
|
||||
uint cellCountX;
|
||||
uint backgroundColor;
|
||||
uint selectionColor;
|
||||
};
|
||||
StructuredBuffer<Cell> cells : register(t0);
|
||||
Texture2D<float4> glyphs : register(t1);
|
||||
|
||||
float4 decodeRGB(uint i)
|
||||
{
|
||||
uint r = i & 0xff;
|
||||
uint g = (i >> 8) & 0xff;
|
||||
uint b = (i >> 16) & 0xff;
|
||||
uint a = i >> 24;
|
||||
return float4(r, g, b, a) / 255.0;
|
||||
}
|
||||
|
||||
uint2 decodeU16x2(uint i)
|
||||
{
|
||||
return uint2(i & 0xffff, i >> 16);
|
||||
}
|
||||
|
||||
float insideRect(float2 pos, float4 boundaries)
|
||||
{
|
||||
float2 v = step(boundaries.xy, pos) - step(boundaries.zw, pos);
|
||||
return v.x * v.y;
|
||||
}
|
||||
|
||||
float4 main(float4 pos: SV_Position): SV_Target
|
||||
{
|
||||
if (!insideRect(pos.xy, viewport))
|
||||
{
|
||||
return decodeRGB(backgroundColor);
|
||||
}
|
||||
|
||||
uint2 cellIndex = pos.xy / cellSize;
|
||||
uint2 cellPos = pos.xy % cellSize;
|
||||
|
||||
Cell cell = cells[cellIndex.y * cellCountX + cellIndex.x];
|
||||
|
||||
uint2 glyphPos = decodeU16x2(cell.glyphPos);
|
||||
uint2 pixelPos = glyphPos + cellPos;
|
||||
float4 alpha = glyphs[pixelPos];
|
||||
|
||||
float3 color = lerp(
|
||||
decodeRGB(cell.color.y).rgb,
|
||||
decodeRGB(cell.color.x).rgb,
|
||||
alpha.rgb
|
||||
);
|
||||
|
||||
if (cell.flags & 1)
|
||||
{
|
||||
color = abs(glyphs[cellPos].rgb - color);
|
||||
}
|
||||
if (cell.flags & 2)
|
||||
{
|
||||
float4 sc = decodeRGB(selectionColor);
|
||||
color = lerp(color, sc.rgb, sc.a);
|
||||
}
|
||||
|
||||
return float4(color, 1);
|
||||
}
|
12
src/renderer/atlas/shader_vs.hlsl
Normal file
12
src/renderer/atlas/shader_vs.hlsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
float4 main(uint id : SV_VERTEXID) : SV_POSITION
|
||||
{
|
||||
// The algorithm below is a fast way to generate a full screen triangle,
|
||||
// published by Bill Bilodeau "Vertex Shader Tricks" at GDC14.
|
||||
// It covers the entire viewport and is faster for the GPU than a quad/rectangle.
|
||||
return float4(
|
||||
float(id / 2) * 4.0 - 1.0,
|
||||
float(id % 2) * 4.0 - 1.0,
|
||||
0.0,
|
||||
1.0
|
||||
);
|
||||
}
|
|
@ -61,7 +61,7 @@ unsigned int FontInfoBase::GetWeight() const
|
|||
return _weight;
|
||||
}
|
||||
|
||||
const std::wstring_view FontInfoBase::GetFaceName() const noexcept
|
||||
const std::wstring& FontInfoBase::GetFaceName() const noexcept
|
||||
{
|
||||
return _faceName;
|
||||
}
|
||||
|
|
|
@ -74,5 +74,6 @@ HRESULT RenderEngineBase::PrepareLineTransform(const LineRendition /*lineRenditi
|
|||
// - Blocks until the engine is able to render without blocking.
|
||||
void RenderEngineBase::WaitUntilCanRender() noexcept
|
||||
{
|
||||
// do nothing by default
|
||||
// Throttle the render loop a bit by default.
|
||||
Sleep(8);
|
||||
}
|
||||
|
|
|
@ -213,12 +213,6 @@ DWORD WINAPI RenderThread::_ThreadProc()
|
|||
LOG_IF_FAILED(_pRenderer->PaintFrame());
|
||||
|
||||
SetEvent(_hPaintCompletedEvent);
|
||||
|
||||
// extra check before we sleep since it's a "long" activity, relatively speaking.
|
||||
if (_fKeepRunning)
|
||||
{
|
||||
Sleep(s_FrameLimitMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
|
|
|
@ -37,8 +37,6 @@ namespace Microsoft::Console::Render
|
|||
static DWORD WINAPI s_ThreadProc(_In_ LPVOID lpParameter);
|
||||
DWORD WINAPI _ThreadProc();
|
||||
|
||||
static DWORD const s_FrameLimitMilliseconds = 8;
|
||||
|
||||
HANDLE _hThread;
|
||||
HANDLE _hEvent;
|
||||
|
||||
|
|
|
@ -1498,18 +1498,13 @@ CATCH_RETURN()
|
|||
// - See https://docs.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains.
|
||||
void DxEngine::WaitUntilCanRender() noexcept
|
||||
{
|
||||
if (!_swapChainFrameLatencyWaitableObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// DxEngine isn't really performant and can easily hold the console lock for 20ms per (full) frame.
|
||||
// Sleeping 8ms per frame thus increases throughput of the concurrently running VtEngine.
|
||||
Sleep(8);
|
||||
|
||||
const auto ret = WaitForSingleObjectEx(
|
||||
_swapChainFrameLatencyWaitableObject.get(),
|
||||
1000, // 1 second timeout (shouldn't ever occur)
|
||||
true);
|
||||
if (ret != WAIT_OBJECT_0)
|
||||
if (_swapChainFrameLatencyWaitableObject)
|
||||
{
|
||||
LOG_WIN32_MSG(ret, "Waiting for swap chain frame latency waitable object returned error or timeout.");
|
||||
WaitForSingleObjectEx(_swapChainFrameLatencyWaitableObject.get(), 1000, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
unsigned char GetFamily() const;
|
||||
unsigned int GetWeight() const;
|
||||
const std::wstring_view GetFaceName() const noexcept;
|
||||
const std::wstring& GetFaceName() const noexcept;
|
||||
unsigned int GetCodePage() const;
|
||||
|
||||
HRESULT FillLegacyNameBuffer(gsl::span<wchar_t> buffer) const;
|
||||
|
|
|
@ -44,27 +44,15 @@ namespace Microsoft::Console::Render
|
|||
};
|
||||
using GridLineSet = til::enumset<GridLines>;
|
||||
|
||||
virtual ~IRenderEngine() = 0;
|
||||
virtual ~IRenderEngine() {}
|
||||
|
||||
protected:
|
||||
IRenderEngine() = default;
|
||||
IRenderEngine(const IRenderEngine&) = default;
|
||||
IRenderEngine(IRenderEngine&&) = default;
|
||||
IRenderEngine& operator=(const IRenderEngine&) = default;
|
||||
IRenderEngine& operator=(IRenderEngine&&) = default;
|
||||
|
||||
public:
|
||||
[[nodiscard]] virtual HRESULT StartPaint() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT EndPaint() noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual bool RequiresContinuousRedraw() noexcept = 0;
|
||||
virtual void WaitUntilCanRender() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT Present() noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT ScrollFrame() noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept = 0;
|
||||
|
@ -72,50 +60,24 @@ namespace Microsoft::Console::Render
|
|||
[[nodiscard]] virtual HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateAll() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT InvalidateTitle(const std::wstring_view proposedTitle) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT PrepareRenderInfo(const RenderFrameInfo& info) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT ResetLineTransform() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PrepareLineTransform(const LineRendition lineRendition,
|
||||
const size_t targetRow,
|
||||
const size_t viewportLeft) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT PrepareLineTransform(const LineRendition lineRendition, const size_t targetRow, const size_t viewportLeft) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintBackground() noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters,
|
||||
const COORD coord,
|
||||
const bool fTrimLeft,
|
||||
const bool lineWrapped) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintBufferGridLines(const GridLineSet lines,
|
||||
const COLORREF color,
|
||||
const size_t cchLine,
|
||||
const COORD coordTarget) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintBufferGridLines(const GridLineSet lines, const COLORREF color, const size_t cchLine, const COORD coordTarget) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT PaintSelection(const SMALL_RECT rect) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT PaintCursor(const CursorOptions& options) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
|
||||
const gsl::not_null<IRenderData*> pData,
|
||||
const bool usingSoftFont,
|
||||
const bool isSettingDefaultBrushes) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired,
|
||||
_Out_ FontInfo& FontInfo) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern,
|
||||
const SIZE cellSize,
|
||||
const size_t centeringHint) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateSoftFont(const gsl::span<const uint16_t> bitPattern, const SIZE cellSize, const size_t centeringHint) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateDpi(const int iDpi) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired,
|
||||
_Out_ FontInfo& FontInfo,
|
||||
const int iDpi) noexcept = 0;
|
||||
|
||||
[[nodiscard]] virtual HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept = 0;
|
||||
[[nodiscard]] virtual HRESULT UpdateTitle(const std::wstring_view newTitle) noexcept = 0;
|
||||
};
|
||||
|
||||
inline Microsoft::Console::Render::IRenderEngine::~IRenderEngine() {}
|
||||
}
|
||||
|
|
|
@ -261,6 +261,13 @@ CATCH_RETURN();
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
// RenderEngineBase defines a WaitUntilCanRender() that sleeps for 8ms to throttle rendering.
|
||||
// But UiaEngine is never the only the engine running. Overriding this function prevents
|
||||
// us from sleeping 16ms per frame, when the other engine also sleeps for 8ms.
|
||||
void UiaEngine::WaitUntilCanRender() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Used to perform longer running presentation steps outside the lock so the
|
||||
// other threads can continue.
|
||||
|
|
|
@ -33,15 +33,13 @@ namespace Microsoft::Console::Render
|
|||
[[nodiscard]] HRESULT Enable() noexcept;
|
||||
[[nodiscard]] HRESULT Disable() noexcept;
|
||||
|
||||
// IRenderEngine Members
|
||||
// IRenderEngine Members
|
||||
[[nodiscard]] HRESULT StartPaint() noexcept override;
|
||||
[[nodiscard]] HRESULT EndPaint() noexcept override;
|
||||
void WaitUntilCanRender() noexcept override;
|
||||
[[nodiscard]] HRESULT Present() noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT PrepareForTeardown(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT ScrollFrame() noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT Invalidate(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCursor(const SMALL_RECT* const psrRegion) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateSystem(const RECT* const prcDirtyClient) noexcept override;
|
||||
|
@ -49,27 +47,16 @@ namespace Microsoft::Console::Render
|
|||
[[nodiscard]] HRESULT InvalidateScroll(const COORD* const pcoordDelta) noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateAll() noexcept override;
|
||||
[[nodiscard]] HRESULT InvalidateCircling(_Out_ bool* const pForcePaint) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT PaintBackground() noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters,
|
||||
COORD const coord,
|
||||
bool const fTrimLeft,
|
||||
const bool lineWrapped) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferGridLines(GridLineSet const lines, COLORREF const color, size_t const cchLine, COORD const coordTarget) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferLine(gsl::span<const Cluster> const clusters, const COORD coord, const bool fTrimLeft, const bool lineWrapped) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintBufferGridLines(const GridLineSet lines, const COLORREF color, const size_t cchLine, const COORD coordTarget) noexcept override;
|
||||
[[nodiscard]] HRESULT PaintSelection(const SMALL_RECT rect) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT PaintCursor(const CursorOptions& options) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes,
|
||||
const gsl::not_null<IRenderData*> pData,
|
||||
const bool usingSoftFont,
|
||||
const bool isSettingDefaultBrushes) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateDpi(int const iDpi) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateDrawingBrushes(const TextAttribute& textAttributes, const gsl::not_null<IRenderData*> pData, const bool usingSoftFont, const bool isSettingDefaultBrushes) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateDpi(const int iDpi) noexcept override;
|
||||
[[nodiscard]] HRESULT UpdateViewport(const SMALL_RECT srNewViewport) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& fiFontInfoDesired, FontInfo& fiFontInfo, int const iDpi) noexcept override;
|
||||
|
||||
[[nodiscard]] HRESULT GetProposedFont(const FontInfoDesired& FontInfoDesired, _Out_ FontInfo& FontInfo, const int iDpi) noexcept override;
|
||||
[[nodiscard]] HRESULT GetDirtyArea(gsl::span<const til::rectangle>& area) noexcept override;
|
||||
[[nodiscard]] HRESULT GetFontSize(_Out_ COORD* const pFontSize) noexcept override;
|
||||
[[nodiscard]] HRESULT IsGlyphWideByFont(const std::wstring_view glyph, _Out_ bool* const pResult) noexcept override;
|
||||
|
|
|
@ -4,374 +4,378 @@
|
|||
#include "precomp.h"
|
||||
#include "inc/CodepointWidthDetector.hpp"
|
||||
|
||||
namespace
|
||||
#pragma warning(disable : 4463)
|
||||
|
||||
struct UnicodeRangeBasic
|
||||
{
|
||||
// used to store range data in CodepointWidthDetector's internal map
|
||||
struct UnicodeRange final
|
||||
{
|
||||
unsigned int lowerBound;
|
||||
unsigned int upperBound;
|
||||
CodepointWidth width;
|
||||
};
|
||||
uint16_t upperBound;
|
||||
// lowerBound = it->upperBound - it->boundWidth
|
||||
// Code points can be up to 2^16, however no range in our table exceeds 2^15.
|
||||
// This is why we store the "width" between the lower and upper boundary instead.
|
||||
uint16_t boundWidth : 15;
|
||||
uint16_t isAmbiguous : 1;
|
||||
};
|
||||
|
||||
static bool operator<(const UnicodeRange& range, const unsigned int searchTerm) noexcept
|
||||
{
|
||||
return range.upperBound < searchTerm;
|
||||
}
|
||||
struct UnicodeRangeSurrogate
|
||||
{
|
||||
uint32_t upperBound;
|
||||
// This fields is identical to the one in UnicodeRangeBasic.
|
||||
// Technically we could store the absolute code point value here,
|
||||
// but it doesn't make any practical performance difference.
|
||||
uint32_t boundWidth : 31;
|
||||
uint32_t isAmbiguous : 1;
|
||||
};
|
||||
|
||||
// Generated by Generate-CodepointWidthsFromUCD.ps1 -Pack:True -Full:False -NoOverrides:False
|
||||
// on 10/25/2020 7:32:04 AM (UTC) from Unicode 13.0.0.
|
||||
// 321205 (0x4E6B5) codepoints covered.
|
||||
// 240 (0xF0) codepoints overridden.
|
||||
// Override path: .\src\types\unicode_width_overrides.xml
|
||||
static constexpr std::array<UnicodeRange, 295> s_wideAndAmbiguousTable{
|
||||
UnicodeRange{ 0xa1, 0xa1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xa4, 0xa4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xa7, 0xa8, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xaa, 0xaa, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xad, 0xae, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xb0, 0xb4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xb6, 0xba, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xbc, 0xbf, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xc6, 0xc6, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xd0, 0xd0, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xd7, 0xd8, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xde, 0xe1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xe6, 0xe6, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xe8, 0xea, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xec, 0xed, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xf0, 0xf0, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xf2, 0xf3, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xf7, 0xfa, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xfc, 0xfc, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xfe, 0xfe, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x101, 0x101, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x111, 0x111, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x113, 0x113, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x11b, 0x11b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x126, 0x127, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x12b, 0x12b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x131, 0x133, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x138, 0x138, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x13f, 0x142, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x144, 0x144, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x148, 0x14b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x14d, 0x14d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x152, 0x153, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x166, 0x167, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x16b, 0x16b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1ce, 0x1ce, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1d0, 0x1d0, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1d2, 0x1d2, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1d4, 0x1d4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1d6, 0x1d6, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1d8, 0x1d8, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1da, 0x1da, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1dc, 0x1dc, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x251, 0x251, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x261, 0x261, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2c4, 0x2c4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2c7, 0x2c7, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2c9, 0x2cb, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2cd, 0x2cd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2d0, 0x2d0, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2d8, 0x2db, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2dd, 0x2dd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2df, 0x2df, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x300, 0x36f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x391, 0x3a1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x3a3, 0x3a9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x3b1, 0x3c1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x3c3, 0x3c9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x401, 0x401, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x410, 0x44f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x451, 0x451, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1100, 0x115f, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2010, 0x2010, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2013, 0x2016, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2018, 0x2019, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x201c, 0x201d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2020, 0x2022, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2024, 0x2027, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2030, 0x2030, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2032, 0x2033, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2035, 0x2035, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x203b, 0x203b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x203e, 0x203e, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2074, 0x2074, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x207f, 0x207f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2081, 0x2084, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x20ac, 0x20ac, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2103, 0x2103, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2105, 0x2105, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2109, 0x2109, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2113, 0x2113, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2116, 0x2116, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2121, 0x2122, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2126, 0x2126, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x212b, 0x212b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2153, 0x2154, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x215b, 0x215e, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2160, 0x216b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2170, 0x2179, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2189, 0x2189, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2190, 0x2199, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x21b8, 0x21b9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x21d2, 0x21d2, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x21d4, 0x21d4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x21e7, 0x21e7, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2200, 0x2200, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2202, 0x2203, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2207, 0x2208, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x220b, 0x220b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x220f, 0x220f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2211, 0x2211, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2215, 0x2215, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x221a, 0x221a, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x221d, 0x2220, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2223, 0x2223, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2225, 0x2225, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2227, 0x222c, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x222e, 0x222e, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2234, 0x2237, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x223c, 0x223d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2248, 0x2248, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x224c, 0x224c, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2252, 0x2252, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2260, 0x2261, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2264, 0x2267, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x226a, 0x226b, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x226e, 0x226f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2282, 0x2283, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2286, 0x2287, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2295, 0x2295, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2299, 0x2299, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x22a5, 0x22a5, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x22bf, 0x22bf, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2312, 0x2312, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x231a, 0x231b, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2329, 0x232a, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x23e9, 0x23ec, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x23f0, 0x23f0, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x23f3, 0x23f3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2460, 0x24e9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x24eb, 0x24ff, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2500, 0x259f, CodepointWidth::Narrow }, // box-drawing and block elements require 1-cell alignment
|
||||
UnicodeRange{ 0x25a0, 0x25a1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25a3, 0x25a9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25b2, 0x25b3, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25b6, 0x25b7, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25bc, 0x25bd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25c0, 0x25c1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25c6, 0x25c8, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25cb, 0x25cb, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25ce, 0x25d1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25e2, 0x25e5, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25ef, 0x25ef, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x25fd, 0x25fe, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2605, 0x2606, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2609, 0x2609, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x260e, 0x260f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2614, 0x2615, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x261c, 0x261c, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x261e, 0x261e, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2640, 0x2640, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2642, 0x2642, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2648, 0x2653, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2660, 0x2661, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2663, 0x2665, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2667, 0x266a, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x266c, 0x266d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x266f, 0x266f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x267f, 0x267f, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2693, 0x2693, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x269e, 0x269f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26a1, 0x26a1, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26aa, 0x26ab, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26bd, 0x26be, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26bf, 0x26bf, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26c4, 0x26c5, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26c6, 0x26cd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26ce, 0x26ce, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26cf, 0x26d3, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26d4, 0x26d4, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26d5, 0x26e1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26e3, 0x26e3, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26e8, 0x26e9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26ea, 0x26ea, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26eb, 0x26f1, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26f2, 0x26f3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26f4, 0x26f4, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26f5, 0x26f5, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26f6, 0x26f9, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26fa, 0x26fa, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26fb, 0x26fc, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x26fd, 0x26fd, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x26fe, 0x26ff, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2705, 0x2705, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x270a, 0x270b, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2728, 0x2728, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x273d, 0x273d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x274c, 0x274c, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x274e, 0x274e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2753, 0x2755, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2757, 0x2757, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2776, 0x277f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2795, 0x2797, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x27b0, 0x27b0, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x27bf, 0x27bf, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2b1b, 0x2b1c, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2b50, 0x2b50, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2b55, 0x2b55, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2b56, 0x2b59, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x2e80, 0x2e99, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2e9b, 0x2ef3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2f00, 0x2fd5, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x2ff0, 0x2ffb, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3000, 0x303e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3041, 0x3096, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3099, 0x30ff, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3105, 0x312f, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3131, 0x318e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3190, 0x31e3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x31f0, 0x321e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3220, 0x3247, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x3248, 0x324f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x3250, 0x4dbf, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x4dc0, 0x4dff, CodepointWidth::Narrow }, // hexagrams are historically narrow
|
||||
UnicodeRange{ 0x4e00, 0xa48c, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xa490, 0xa4c6, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xa960, 0xa97c, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xac00, 0xd7a3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xe000, 0xf8ff, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xf900, 0xfaff, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xfe00, 0xfe0f, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xfe10, 0xfe19, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xfe20, 0xfe2f, CodepointWidth::Narrow }, // narrow combining ligatures (split into left/right halves, which take 2 columns together)
|
||||
UnicodeRange{ 0xfe30, 0xfe52, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xfe54, 0xfe66, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xfe68, 0xfe6b, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xff01, 0xff60, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xffe0, 0xffe6, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xfffd, 0xfffd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x16fe0, 0x16fe4, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x16ff0, 0x16ff1, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x17000, 0x187f7, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x18800, 0x18cd5, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x18d00, 0x18d08, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1b000, 0x1b11e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1b150, 0x1b152, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1b164, 0x1b167, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1b170, 0x1b2fb, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f004, 0x1f004, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f0cf, 0x1f0cf, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f100, 0x1f10a, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f110, 0x1f12d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f130, 0x1f169, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f170, 0x1f18d, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f18e, 0x1f18e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f18f, 0x1f190, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f191, 0x1f19a, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f19b, 0x1f1ac, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x1f1e6, 0x1f202, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f210, 0x1f23b, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f240, 0x1f248, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f250, 0x1f251, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f260, 0x1f265, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f300, 0x1f320, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f32d, 0x1f335, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f337, 0x1f37c, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f37e, 0x1f393, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f3a0, 0x1f3ca, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f3cf, 0x1f3d3, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f3e0, 0x1f3f0, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f3f4, 0x1f3f4, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f3f8, 0x1f43e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f440, 0x1f440, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f442, 0x1f4fc, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f4ff, 0x1f53d, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f54b, 0x1f54e, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f550, 0x1f567, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f57a, 0x1f57a, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f595, 0x1f596, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f5a4, 0x1f5a4, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f5fb, 0x1f64f, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f680, 0x1f6c5, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f6cc, 0x1f6cc, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f6d0, 0x1f6d2, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f6d5, 0x1f6d7, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f6eb, 0x1f6ec, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f6f4, 0x1f6fc, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f7e0, 0x1f7eb, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f90c, 0x1f93a, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f93c, 0x1f945, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f947, 0x1f978, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f97a, 0x1f9cb, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1f9cd, 0x1f9ff, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fa70, 0x1fa74, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fa78, 0x1fa7a, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fa80, 0x1fa86, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fa90, 0x1faa8, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fab0, 0x1fab6, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fac0, 0x1fac2, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x1fad0, 0x1fad6, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x20000, 0x2fffd, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0x30000, 0x3fffd, CodepointWidth::Wide },
|
||||
UnicodeRange{ 0xe0100, 0xe01ef, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0xf0000, 0xffffd, CodepointWidth::Ambiguous },
|
||||
UnicodeRange{ 0x100000, 0x10fffd, CodepointWidth::Ambiguous },
|
||||
};
|
||||
constexpr bool operator<(const UnicodeRangeBasic& range, const uint16_t searchTerm) noexcept
|
||||
{
|
||||
return range.upperBound < searchTerm;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Constructs an instance of the CodepointWidthDetector class
|
||||
CodepointWidthDetector::CodepointWidthDetector() noexcept :
|
||||
_fallbackCache{},
|
||||
_pfnFallbackMethod{}
|
||||
constexpr bool operator<(const UnicodeRangeSurrogate& range, const uint32_t searchTerm) noexcept
|
||||
{
|
||||
return range.upperBound < searchTerm;
|
||||
}
|
||||
|
||||
// The following two tables are generated by:
|
||||
// * Downloading ucd.nounihan.flat.xml from https://www.unicode.org/Public/UCD/latest/ucdxml
|
||||
// * Running .\tools\Generate-CodepointWidthsFromUCD.ps1 -Pack -OverridePath .\src\types\unicode_width_overrides.xml ucd.nounihan.flat.xml
|
||||
|
||||
// Generated by Generate-CodepointWidthsFromUCD.ps1 -Pack:$True -Full:$False -NoOverrides:$False
|
||||
// on 10.10.2021 22:40:05 (UTC) from Unicode 14.0.0.
|
||||
// 321259 (0x4E6EB) codepoints covered.
|
||||
// 240 (0xF0) codepoints overridden.
|
||||
// Override path: .\src\types\unicode_width_overrides.xml
|
||||
static constexpr std::array<UnicodeRangeBasic, 226> tableBasic{ {
|
||||
UnicodeRangeBasic{ 0xa1, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xa4, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xa8, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0xaa, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xae, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0xb4, 0x4, 1 },
|
||||
UnicodeRangeBasic{ 0xba, 0x4, 1 },
|
||||
UnicodeRangeBasic{ 0xbf, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0xc6, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xd0, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xd8, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0xe1, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0xe6, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xea, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0xed, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0xf0, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xf3, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0xfa, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0xfc, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0xfe, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x101, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x111, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x113, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x11b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x127, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x12b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x133, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0x138, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x142, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x144, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x14b, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x14d, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x153, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x167, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x16b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1ce, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1d0, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1d2, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1d4, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1d6, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1d8, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1da, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x1dc, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x251, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x261, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2c4, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2c7, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2cb, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0x2cd, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2d0, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2db, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x2dd, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2df, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x36f, 0x6f, 1 },
|
||||
UnicodeRangeBasic{ 0x3a1, 0x10, 1 },
|
||||
UnicodeRangeBasic{ 0x3a9, 0x6, 1 },
|
||||
UnicodeRangeBasic{ 0x3c1, 0x10, 1 },
|
||||
UnicodeRangeBasic{ 0x3c9, 0x6, 1 },
|
||||
UnicodeRangeBasic{ 0x401, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x44f, 0x3f, 1 },
|
||||
UnicodeRangeBasic{ 0x451, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x115f, 0x5f, 0 },
|
||||
UnicodeRangeBasic{ 0x2010, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2016, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x2019, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x201d, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2022, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0x2027, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x2030, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2033, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2035, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x203b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x203e, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2074, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x207f, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2084, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x20ac, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2103, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2105, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2109, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2113, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2116, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2122, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2126, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x212b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2154, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x215e, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x216b, 0xb, 1 },
|
||||
UnicodeRangeBasic{ 0x2179, 0x9, 1 },
|
||||
UnicodeRangeBasic{ 0x2189, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2199, 0x9, 1 },
|
||||
UnicodeRangeBasic{ 0x21b9, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x21d2, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x21d4, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x21e7, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2200, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2203, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2208, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x220b, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x220f, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2211, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2215, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x221a, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2220, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x2223, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2225, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x222c, 0x5, 1 },
|
||||
UnicodeRangeBasic{ 0x222e, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2237, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x223d, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2248, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x224c, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2252, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2261, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2267, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x226b, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x226f, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2283, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2287, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2295, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2299, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x22a5, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x22bf, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2312, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x231b, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x232a, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x23ec, 0x3, 0 },
|
||||
UnicodeRangeBasic{ 0x23f0, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x23f3, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x24e9, 0x89, 1 },
|
||||
UnicodeRangeBasic{ 0x24ff, 0x14, 1 },
|
||||
UnicodeRangeBasic{ 0x25a1, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x25a9, 0x6, 1 },
|
||||
UnicodeRangeBasic{ 0x25b3, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x25b7, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x25bd, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x25c1, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x25c8, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0x25cb, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x25d1, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x25e5, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x25ef, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x25fe, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x2606, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2609, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x260f, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2615, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x261c, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x261e, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2640, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2642, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x2653, 0xb, 0 },
|
||||
UnicodeRangeBasic{ 0x2661, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2665, 0x2, 1 },
|
||||
UnicodeRangeBasic{ 0x266a, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x266d, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x266f, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x267f, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x2693, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x269f, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x26a1, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26ab, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x26be, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x26bf, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x26c5, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x26cd, 0x7, 1 },
|
||||
UnicodeRangeBasic{ 0x26ce, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26d3, 0x4, 1 },
|
||||
UnicodeRangeBasic{ 0x26d4, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26e1, 0xc, 1 },
|
||||
UnicodeRangeBasic{ 0x26e3, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x26e9, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x26ea, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26f1, 0x6, 1 },
|
||||
UnicodeRangeBasic{ 0x26f3, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x26f4, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x26f5, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26f9, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x26fa, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26fc, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x26fd, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x26ff, 0x1, 1 },
|
||||
UnicodeRangeBasic{ 0x2705, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x270b, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x2728, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x273d, 0x0, 1 },
|
||||
UnicodeRangeBasic{ 0x274c, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x274e, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x2755, 0x2, 0 },
|
||||
UnicodeRangeBasic{ 0x2757, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x277f, 0x9, 1 },
|
||||
UnicodeRangeBasic{ 0x2797, 0x2, 0 },
|
||||
UnicodeRangeBasic{ 0x27b0, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x27bf, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x2b1c, 0x1, 0 },
|
||||
UnicodeRangeBasic{ 0x2b50, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x2b55, 0x0, 0 },
|
||||
UnicodeRangeBasic{ 0x2b59, 0x3, 1 },
|
||||
UnicodeRangeBasic{ 0x2e99, 0x19, 0 },
|
||||
UnicodeRangeBasic{ 0x2ef3, 0x58, 0 },
|
||||
UnicodeRangeBasic{ 0x2fd5, 0xd5, 0 },
|
||||
UnicodeRangeBasic{ 0x2ffb, 0xb, 0 },
|
||||
UnicodeRangeBasic{ 0x303e, 0x3e, 0 },
|
||||
UnicodeRangeBasic{ 0x3096, 0x55, 0 },
|
||||
UnicodeRangeBasic{ 0x30ff, 0x66, 0 },
|
||||
UnicodeRangeBasic{ 0x312f, 0x2a, 0 },
|
||||
UnicodeRangeBasic{ 0x318e, 0x5d, 0 },
|
||||
UnicodeRangeBasic{ 0x31e3, 0x53, 0 },
|
||||
UnicodeRangeBasic{ 0x321e, 0x2e, 0 },
|
||||
UnicodeRangeBasic{ 0x3247, 0x27, 0 },
|
||||
UnicodeRangeBasic{ 0x324f, 0x7, 1 },
|
||||
UnicodeRangeBasic{ 0x4dbf, 0x1b6f, 0 },
|
||||
UnicodeRangeBasic{ 0xa48c, 0x568c, 0 },
|
||||
UnicodeRangeBasic{ 0xa4c6, 0x36, 0 },
|
||||
UnicodeRangeBasic{ 0xa97c, 0x1c, 0 },
|
||||
UnicodeRangeBasic{ 0xd7a3, 0x2ba3, 0 },
|
||||
UnicodeRangeBasic{ 0xf8ff, 0x18ff, 1 },
|
||||
UnicodeRangeBasic{ 0xfaff, 0x1ff, 0 },
|
||||
UnicodeRangeBasic{ 0xfe0f, 0xf, 1 },
|
||||
UnicodeRangeBasic{ 0xfe19, 0x9, 0 },
|
||||
UnicodeRangeBasic{ 0xfe52, 0x22, 0 },
|
||||
UnicodeRangeBasic{ 0xfe66, 0x12, 0 },
|
||||
UnicodeRangeBasic{ 0xfe6b, 0x3, 0 },
|
||||
UnicodeRangeBasic{ 0xff60, 0x5f, 0 },
|
||||
UnicodeRangeBasic{ 0xffe6, 0x6, 0 },
|
||||
UnicodeRangeBasic{ 0xfffd, 0x0, 1 },
|
||||
} };
|
||||
static constexpr std::array<UnicodeRangeSurrogate, 71> tableSurrogates{ {
|
||||
UnicodeRangeSurrogate{ 0x16fe4, 0x4, 0 },
|
||||
UnicodeRangeSurrogate{ 0x16ff1, 0x1, 0 },
|
||||
UnicodeRangeSurrogate{ 0x187f7, 0x17f7, 0 },
|
||||
UnicodeRangeSurrogate{ 0x18cd5, 0x4d5, 0 },
|
||||
UnicodeRangeSurrogate{ 0x18d08, 0x8, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1aff3, 0x3, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1affb, 0x6, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1affe, 0x1, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1b122, 0x122, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1b152, 0x2, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1b167, 0x3, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1b2fb, 0x18b, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f004, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f0cf, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f10a, 0xa, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f12d, 0x1d, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f169, 0x39, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f18d, 0x1d, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f18e, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f190, 0x1, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f19a, 0x9, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f1ac, 0x11, 1 },
|
||||
UnicodeRangeSurrogate{ 0x1f202, 0x1c, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f23b, 0x2b, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f248, 0x8, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f251, 0x1, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f265, 0x5, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f320, 0x20, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f335, 0x8, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f37c, 0x45, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f393, 0x15, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f3ca, 0x2a, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f3d3, 0x4, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f3f0, 0x10, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f3f4, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f43e, 0x46, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f440, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f4fc, 0xba, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f53d, 0x3e, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f54e, 0x3, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f567, 0x17, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f57a, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f596, 0x1, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f5a4, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f64f, 0x54, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6c5, 0x45, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6cc, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6d2, 0x2, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6d7, 0x2, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6df, 0x2, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6ec, 0x1, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f6fc, 0x8, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f7eb, 0xb, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f7f0, 0x0, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f93a, 0x2e, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f945, 0x9, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1f9ff, 0xb8, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fa74, 0x4, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fa7c, 0x4, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fa86, 0x6, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1faac, 0x1c, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1faba, 0xa, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fac5, 0x5, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fad9, 0x9, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1fae7, 0x7, 0 },
|
||||
UnicodeRangeSurrogate{ 0x1faf6, 0x6, 0 },
|
||||
UnicodeRangeSurrogate{ 0x2fffd, 0xfffd, 0 },
|
||||
UnicodeRangeSurrogate{ 0x3fffd, 0xfffd, 0 },
|
||||
UnicodeRangeSurrogate{ 0xe01ef, 0xef, 1 },
|
||||
UnicodeRangeSurrogate{ 0xffffd, 0xfffd, 1 },
|
||||
UnicodeRangeSurrogate{ 0x10fffd, 0xfffd, 1 },
|
||||
} };
|
||||
|
||||
// Routine Description:
|
||||
// - returns the width type of codepoint as fast as we can by using quick lookup table and fallback cache.
|
||||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint to search for
|
||||
// Return Value:
|
||||
// - the width type of the codepoint
|
||||
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) const
|
||||
CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view& glyph) const noexcept
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, glyph.empty());
|
||||
if (glyph.size() == 1)
|
||||
switch (glyph.size())
|
||||
{
|
||||
// We first attempt to look at our custom quick lookup table of char width preferences.
|
||||
const auto width = GetQuickCharWidth(glyph.front());
|
||||
|
||||
// If it's invalid, the quick width had no opinion, so go to the lookup table.
|
||||
if (width == CodepointWidth::Invalid)
|
||||
{
|
||||
return _lookupGlyphWidthWithCache(glyph);
|
||||
}
|
||||
// If it's ambiguous, the quick width wanted us to ask the font directly, try that if we can.
|
||||
// If not, go to the lookup table.
|
||||
else if (width == CodepointWidth::Ambiguous)
|
||||
{
|
||||
if (_pfnFallbackMethod)
|
||||
{
|
||||
return _checkFallbackViaCache(glyph) ? CodepointWidth::Wide : CodepointWidth::Ambiguous;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _lookupGlyphWidthWithCache(glyph);
|
||||
}
|
||||
}
|
||||
// Otherwise, return Width as it is.
|
||||
else
|
||||
{
|
||||
return width;
|
||||
}
|
||||
case 0:
|
||||
return CodepointWidth::Ambiguous;
|
||||
case 1:
|
||||
{
|
||||
const uint16_t codepoint = til::at(glyph, 0);
|
||||
// ASCII code points below 0x80 are fairly common.
|
||||
// We shouldn't have to call _getCodepointWidth for that.
|
||||
// In fact those code points aren't even in tableBasic.
|
||||
return codepoint < 0x80 ? CodepointWidth::Narrow : _getCodepointWidth(tableBasic, codepoint, glyph);
|
||||
}
|
||||
else
|
||||
case 2:
|
||||
{
|
||||
return _lookupGlyphWidthWithCache(glyph);
|
||||
uint32_t codepoint = (til::at(glyph, 0) & 0x3FF) << 10;
|
||||
codepoint |= til::at(glyph, 1) & 0x3FF;
|
||||
codepoint += 0x10000;
|
||||
return _getCodepointWidth(tableSurrogates, codepoint, glyph);
|
||||
}
|
||||
default:
|
||||
return CodepointWidth::Wide;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,13 +387,7 @@ CodepointWidth CodepointWidthDetector::GetWidth(const std::wstring_view glyph) c
|
|||
// - true if wch is wide
|
||||
bool CodepointWidthDetector::IsWide(const wchar_t wch) const noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
return IsWide({ &wch, 1 });
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
return true;
|
||||
return wch < 0x80 ? false : IsWide({ &wch, 1 });
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
|
@ -398,75 +396,11 @@ bool CodepointWidthDetector::IsWide(const wchar_t wch) const noexcept
|
|||
// - glyph - the utf16 encoded codepoint to check width of
|
||||
// Return Value:
|
||||
// - true if codepoint is wide
|
||||
bool CodepointWidthDetector::IsWide(const std::wstring_view glyph) const
|
||||
bool CodepointWidthDetector::IsWide(const std::wstring_view& glyph) const noexcept
|
||||
{
|
||||
return GetWidth(glyph) == CodepointWidth::Wide;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - returns the width type of codepoint by searching the map generated from the unicode spec
|
||||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint to search for
|
||||
// Return Value:
|
||||
// - the width type of the codepoint
|
||||
CodepointWidth CodepointWidthDetector::_lookupGlyphWidth(const std::wstring_view glyph) const
|
||||
{
|
||||
if (glyph.empty())
|
||||
{
|
||||
return CodepointWidth::Invalid;
|
||||
}
|
||||
|
||||
const auto codepoint = _extractCodepoint(glyph);
|
||||
const auto it = std::lower_bound(s_wideAndAmbiguousTable.begin(), s_wideAndAmbiguousTable.end(), codepoint);
|
||||
|
||||
// For characters that are not _in_ the table, lower_bound will return the nearest item that is.
|
||||
// We must check its bounds to make sure that our hit was a true hit.
|
||||
if (it != s_wideAndAmbiguousTable.end() && codepoint >= it->lowerBound && codepoint <= it->upperBound)
|
||||
{
|
||||
return it->width;
|
||||
}
|
||||
|
||||
return CodepointWidth::Narrow;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - returns the width type of codepoint using fallback methods.
|
||||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint to check width of
|
||||
// Return Value:
|
||||
// - the width type of the codepoint
|
||||
CodepointWidth CodepointWidthDetector::_lookupGlyphWidthWithCache(const std::wstring_view glyph) const noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
// Use our generated table to try to lookup the width based on the Unicode standard.
|
||||
const CodepointWidth width = _lookupGlyphWidth(glyph);
|
||||
|
||||
// If it's ambiguous, then ask the font if we can.
|
||||
if (width == CodepointWidth::Ambiguous)
|
||||
{
|
||||
if (_pfnFallbackMethod)
|
||||
{
|
||||
return _checkFallbackViaCache(glyph) ? CodepointWidth::Wide : CodepointWidth::Ambiguous;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CodepointWidth::Ambiguous;
|
||||
}
|
||||
}
|
||||
// If it's not ambiguous, it should say wide or narrow.
|
||||
else
|
||||
{
|
||||
return width;
|
||||
}
|
||||
}
|
||||
CATCH_LOG();
|
||||
|
||||
// If we got this far, we couldn't figure it out.
|
||||
// It's better to be too wide than too narrow.
|
||||
return CodepointWidth::Wide;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Checks the fallback function but caches the results until the font changes
|
||||
// because the lookup function is usually very expensive and will return the same results
|
||||
|
@ -474,47 +408,29 @@ CodepointWidth CodepointWidthDetector::_lookupGlyphWidthWithCache(const std::wst
|
|||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint to check width of
|
||||
// - true if codepoint is wide or false if it is narrow
|
||||
bool CodepointWidthDetector::_checkFallbackViaCache(const std::wstring_view glyph) const
|
||||
CodepointWidth CodepointWidthDetector::_checkFallbackViaCache(uint32_t codepoint, const std::wstring_view& glyph) const noexcept
|
||||
try
|
||||
{
|
||||
const std::wstring findMe{ glyph };
|
||||
if (!_pfnFallbackMethod)
|
||||
{
|
||||
return CodepointWidth::Narrow;
|
||||
}
|
||||
|
||||
// TODO: Cache needs to be emptied when font changes.
|
||||
const auto it = _fallbackCache.find(findMe);
|
||||
if (it == _fallbackCache.end())
|
||||
{
|
||||
auto result = _pfnFallbackMethod(glyph);
|
||||
_fallbackCache.insert_or_assign(findMe, result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
const auto it = _fallbackCache.find(codepoint);
|
||||
if (it != _fallbackCache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - extract unicode codepoint from utf16 encoding
|
||||
// Arguments:
|
||||
// - glyph - the utf16 encoded codepoint convert
|
||||
// Return Value:
|
||||
// - the codepoint being stored
|
||||
unsigned int CodepointWidthDetector::_extractCodepoint(const std::wstring_view glyph) noexcept
|
||||
const auto result = _pfnFallbackMethod(glyph) ? CodepointWidth::Wide : CodepointWidth::Narrow;
|
||||
_fallbackCache.insert_or_assign(codepoint, result);
|
||||
return result;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (glyph.size() == 1)
|
||||
{
|
||||
return static_cast<unsigned int>(glyph.front());
|
||||
}
|
||||
else
|
||||
{
|
||||
const unsigned int mask = 0x3FF;
|
||||
// leading bits, shifted over to make space for trailing bits
|
||||
unsigned int codepoint = (glyph.at(0) & mask) << 10;
|
||||
// trailing bits
|
||||
codepoint |= (glyph.at(1) & mask);
|
||||
// 0x10000 is subtracted from the codepoint to encode a surrogate pair, add it back
|
||||
codepoint += 0x10000;
|
||||
return codepoint;
|
||||
}
|
||||
LOG_CAUGHT_EXCEPTION();
|
||||
return CodepointWidth::Narrow;
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -527,9 +443,9 @@ unsigned int CodepointWidthDetector::_extractCodepoint(const std::wstring_view g
|
|||
// - pfnFallback - the function to use as the fallback method.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wstring_view)> pfnFallback)
|
||||
void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wstring_view&)> pfnFallback) noexcept
|
||||
{
|
||||
_pfnFallbackMethod = pfnFallback;
|
||||
_pfnFallbackMethod = std::move(pfnFallback);
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
|
@ -542,5 +458,6 @@ void CodepointWidthDetector::SetFallbackMethod(std::function<bool(const std::wst
|
|||
// - <none>
|
||||
void CodepointWidthDetector::NotifyFontChanged() const noexcept
|
||||
{
|
||||
#pragma warning(suppress : 26447) // The function is declared 'noexcept' but calls function 'clear()' which may throw exceptions (f.6).
|
||||
_fallbackCache.clear();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ static CodepointWidthDetector widthDetector;
|
|||
// Function Description:
|
||||
// - determines if the glyph represented by the string of characters should be
|
||||
// wide or not. See CodepointWidthDetector::IsWide
|
||||
bool IsGlyphFullWidth(const std::wstring_view glyph)
|
||||
bool IsGlyphFullWidth(const std::wstring_view& glyph) noexcept
|
||||
{
|
||||
return widthDetector.IsWide(glyph);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ bool IsGlyphFullWidth(const wchar_t wch) noexcept
|
|||
// - pfnFallback - the function to use as the fallback method.
|
||||
// Return Value:
|
||||
// - <none>
|
||||
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view)> pfnFallback)
|
||||
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view&)> pfnFallback)
|
||||
{
|
||||
widthDetector.SetFallbackMethod(pfnFallback);
|
||||
}
|
||||
|
|
|
@ -130,49 +130,7 @@
|
|||
return cchTarget;
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - naively determines the width of a UCS2 encoded wchar
|
||||
// Arguments:
|
||||
// - wch - the wchar_t to measure
|
||||
// Return Value:
|
||||
// - CodepointWidth indicating width of wch
|
||||
// Notes:
|
||||
// 04-08-92 ShunK Created.
|
||||
// Jul-27-1992 KazuM Added Screen Information and Code Page Information.
|
||||
// Jan-29-1992 V-Hirots Substruct Screen Information.
|
||||
// Oct-06-1996 KazuM Not use RtlUnicodeToMultiByteSize and WideCharToMultiByte
|
||||
// Because 950 (Chinese Traditional) only defined 13500 chars,
|
||||
// and unicode defined almost 18000 chars.
|
||||
// So there are almost 4000 chars can not be mapped to big5 code.
|
||||
// Apr-30-2015 MiNiksa Corrected unknown character code assumption. Max Width in Text Metric
|
||||
// is not reliable for calculating half/full width. Must use current
|
||||
// display font data (cached) instead.
|
||||
// May-23-2017 migrie Forced Box-Drawing Characters (x2500-x257F) to narrow.
|
||||
// Jan-16-2018 migrie Separated core lookup from asking the renderer the width
|
||||
// May-01-2019 MiNiksa Forced lookup-via-renderer for retroactively recategorized emoji
|
||||
// that used to be narrow but now might be wide. (approx x2194-x2b55, not inclusive)
|
||||
// Also forced block characters segment (x2580-x259F) to narrow
|
||||
// Oct-25-2020 DuHowett Replaced the entire table with a set of overrides that get built into
|
||||
// CodepointWidthDetector (unicode_width_overrides.xml)
|
||||
CodepointWidth GetQuickCharWidth(const wchar_t wch) noexcept
|
||||
wchar_t Utf16ToUcs2(const std::wstring_view charData) noexcept
|
||||
{
|
||||
if (0x20 <= wch && wch <= 0x7e)
|
||||
{
|
||||
/* ASCII */
|
||||
return CodepointWidth::Narrow;
|
||||
}
|
||||
return CodepointWidth::Invalid;
|
||||
}
|
||||
|
||||
wchar_t Utf16ToUcs2(const std::wstring_view charData)
|
||||
{
|
||||
THROW_HR_IF(E_INVALIDARG, charData.empty());
|
||||
if (charData.size() > 1)
|
||||
{
|
||||
return UNICODE_REPLACEMENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
return charData.front();
|
||||
}
|
||||
return charData.size() == 1 ? til::at(charData, 0) : UNICODE_REPLACEMENT;
|
||||
}
|
||||
|
|
|
@ -14,26 +14,22 @@ Author:
|
|||
#pragma once
|
||||
|
||||
#include "convert.hpp"
|
||||
#include <functional>
|
||||
|
||||
static_assert(sizeof(unsigned int) == sizeof(wchar_t) * 2,
|
||||
"UnicodeRange expects to be able to store a unicode codepoint in an unsigned int");
|
||||
|
||||
// use to measure the width of a codepoint
|
||||
class CodepointWidthDetector final
|
||||
{
|
||||
public:
|
||||
CodepointWidthDetector() noexcept;
|
||||
CodepointWidthDetector() noexcept = default;
|
||||
|
||||
CodepointWidthDetector(const CodepointWidthDetector&) = delete;
|
||||
CodepointWidthDetector(CodepointWidthDetector&&) = delete;
|
||||
~CodepointWidthDetector() = default;
|
||||
CodepointWidthDetector& operator=(const CodepointWidthDetector&) = delete;
|
||||
CodepointWidthDetector& operator=(CodepointWidthDetector&&) = delete;
|
||||
|
||||
CodepointWidth GetWidth(const std::wstring_view glyph) const;
|
||||
bool IsWide(const std::wstring_view glyph) const;
|
||||
CodepointWidth GetWidth(const std::wstring_view& glyph) const noexcept;
|
||||
bool IsWide(const std::wstring_view& glyph) const noexcept;
|
||||
bool IsWide(const wchar_t wch) const noexcept;
|
||||
void SetFallbackMethod(std::function<bool(const std::wstring_view)> pfnFallback);
|
||||
void SetFallbackMethod(std::function<bool(const std::wstring_view&)> pfnFallback) noexcept;
|
||||
void NotifyFontChanged() const noexcept;
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
|
@ -41,11 +37,22 @@ public:
|
|||
#endif
|
||||
|
||||
private:
|
||||
CodepointWidth _lookupGlyphWidth(const std::wstring_view glyph) const;
|
||||
CodepointWidth _lookupGlyphWidthWithCache(const std::wstring_view glyph) const noexcept;
|
||||
bool _checkFallbackViaCache(const std::wstring_view glyph) const;
|
||||
static unsigned int _extractCodepoint(const std::wstring_view glyph) noexcept;
|
||||
template<typename T, typename U>
|
||||
CodepointWidth _getCodepointWidth(const T& table, U codepoint, const std::wstring_view& glyph) const noexcept
|
||||
{
|
||||
#pragma warning(suppress : 26447) // The function is declared 'noexcept' but calls function 'lower_bound<...>()' which may throw exceptions (f.6).
|
||||
const auto it = std::lower_bound(table.begin(), table.end(), codepoint);
|
||||
|
||||
mutable std::unordered_map<std::wstring, bool> _fallbackCache;
|
||||
std::function<bool(std::wstring_view)> _pfnFallbackMethod;
|
||||
// (it->upperBound - it->boundWidth) is equal to the lowerBound of the code point range.
|
||||
if (it != table.end() && codepoint >= (it->upperBound - it->boundWidth)) {
|
||||
return it->isAmbiguous ? _checkFallbackViaCache(codepoint, glyph) : CodepointWidth::Wide;
|
||||
}
|
||||
|
||||
return CodepointWidth::Narrow;
|
||||
}
|
||||
|
||||
CodepointWidth _checkFallbackViaCache(uint32_t codepoint, const std::wstring_view& glyph) const noexcept;
|
||||
|
||||
mutable std::unordered_map<uint32_t, CodepointWidth> _fallbackCache;
|
||||
std::function<bool(const std::wstring_view&)> _pfnFallbackMethod;
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ Abstract:
|
|||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
bool IsGlyphFullWidth(const std::wstring_view glyph);
|
||||
bool IsGlyphFullWidth(const std::wstring_view& glyph) noexcept;
|
||||
bool IsGlyphFullWidth(const wchar_t wch) noexcept;
|
||||
void SetGlyphWidthFallback(std::function<bool(std::wstring_view)> pfnFallback);
|
||||
void SetGlyphWidthFallback(std::function<bool(const std::wstring_view&)> pfnFallback);
|
||||
void NotifyGlyphWidthFontChanged() noexcept;
|
||||
|
|
|
@ -34,6 +34,4 @@ enum class CodepointWidth : BYTE
|
|||
[[nodiscard]] size_t GetALengthFromW(const UINT codepage,
|
||||
const std::wstring_view source);
|
||||
|
||||
CodepointWidth GetQuickCharWidth(const wchar_t wch) noexcept;
|
||||
|
||||
wchar_t Utf16ToUcs2(const std::wstring_view charData);
|
||||
wchar_t Utf16ToUcs2(const std::wstring_view charData) noexcept;
|
||||
|
|
|
@ -166,7 +166,10 @@ Class UnicodeRangeList : System.Collections.Generic.List[Object] {
|
|||
|
||||
ReplaceUnicodeRange([UnicodeRange]$newRange) {
|
||||
$subset = [System.Collections.Generic.List[Object]]::New(3)
|
||||
$subset.Add($newRange)
|
||||
|
||||
if ($newRange.Width -ne [CodepointWidth]::Narrow) {
|
||||
$subset.Add($newRange)
|
||||
}
|
||||
|
||||
$i = $this._FindInsertionPoint($newRange.Start)
|
||||
|
||||
|
@ -260,21 +263,26 @@ If (-not $NoOverrides) {
|
|||
}
|
||||
}
|
||||
|
||||
# Emit Code
|
||||
" // Generated by {0} -Pack:{1} -Full:{2} -NoOverrides:{3}" -f $MyInvocation.MyCommand.Name, $Pack, $Full, $NoOverrides
|
||||
" // on {0} (UTC) from {1}." -f (Get-Date -AsUTC), $InputObject.ucd.description
|
||||
" // {0} (0x{0:X}) codepoints covered." -f $c
|
||||
If (-not $NoOverrides) {
|
||||
" // {0} (0x{0:X}) codepoints overridden." -f $overrideCount
|
||||
" // Override path: {0}" -f $OverridePath
|
||||
}
|
||||
" static constexpr std::array<UnicodeRange, {0}> s_wideAndAmbiguousTable{{" -f $ranges.Count
|
||||
ForEach($_ in $ranges) {
|
||||
$comment = ""
|
||||
if ($null -ne $_.Comment) {
|
||||
# We only vend comments when we aren't packing tightly
|
||||
$comment = " // {0}" -f $_.Comment
|
||||
function Emit-Table([string] $type, [string] $name, [UnicodeRange[]] $ranges) {
|
||||
"static constexpr std::array<$type, $($ranges.Count)> $name{ {"
|
||||
foreach ($_ in $ranges) {
|
||||
$comment = ""
|
||||
if ($_.Comment) {
|
||||
# We only vend comments when we aren't packing tightly
|
||||
$comment = " // $($_.Comment)"
|
||||
}
|
||||
" $type{{ 0x{0:x}, 0x{1:x}, {2} }},$comment" -f $_.End, ($_.End - $_.Start), ($_.Width -eq [CodepointWidth]::Ambiguous ? 1 : 0)
|
||||
}
|
||||
" UnicodeRange{{ 0x{0:x}, 0x{1:x}, CodepointWidth::{2} }},{3}" -f $_.Start, $_.End, $_.Width, $comment
|
||||
"} };"
|
||||
}
|
||||
" };"
|
||||
|
||||
# Emit Code
|
||||
"// Generated by {0} -Pack:`${1} -Full:`${2} -NoOverrides:`${3}" -f $MyInvocation.MyCommand.Name, $Pack, $Full, $NoOverrides
|
||||
"// on {0} (UTC) from {1}." -f (Get-Date -AsUTC), $InputObject.ucd.description
|
||||
"// {0} (0x{0:X}) codepoints covered." -f $c
|
||||
If (-not $NoOverrides) {
|
||||
"// {0} (0x{0:X}) codepoints overridden." -f $overrideCount
|
||||
"// Override path: {0}" -f $OverridePath
|
||||
}
|
||||
Emit-Table "UnicodeRangeBasic" "tableBasic" ($ranges | Where-Object { $_.End -lt 0x10000 })
|
||||
Emit-Table "UnicodeRangeSurrogate" "tableSurrogates" ($ranges | Where-Object { $_.End -ge 0x10000 })
|
||||
|
|
Loading…
Reference in a new issue