This commit is contained in:
Leonard Hecker 2021-10-11 17:10:31 +02:00
parent 70eeea68e4
commit ebbc14c113
14 changed files with 476 additions and 623 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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;

View file

@ -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;

View file

@ -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 })