diff --git a/sakura_core/charset/codechecker.h b/sakura_core/charset/codechecker.h index 738a24e7cf..5a2e483c5a 100644 --- a/sakura_core/charset/codechecker.h +++ b/sakura_core/charset/codechecker.h @@ -392,8 +392,7 @@ char32_t ConvertToUtf32(std::wstring_view text) { * 文字列がIVSの異体字セレクタで始まっているか判定する */ inline bool IsVariationSelector(std::wstring_view text) { - const auto cp = ConvertToUtf32(text); - return 0xe0100 <= cp && cp <= 0xe01ef; + return (2 <= text.size()) && (text[0] == 0xDB40) && (0xDD00 <= text[1]) && (text[1] <= 0xDDEF); } //! 上位バイトと下位バイトを交換 (主に UTF-16 LE/BE 向け) diff --git a/sakura_core/mem/CNativeW.cpp b/sakura_core/mem/CNativeW.cpp index dbd8e8a98d..1365913ff2 100644 --- a/sakura_core/mem/CNativeW.cpp +++ b/sakura_core/mem/CNativeW.cpp @@ -397,7 +397,7 @@ CLogicInt CNativeW::GetSizeOfChar( const wchar_t* pData, int nDataLen, int nIdx } // IVSの異体字セレクタチェック - if (IsVariationSelector(pData + nIdx + 1)) { + if (IsVariationSelector(std::wstring_view(pData + nIdx + 1, nDataLen - (nIdx + 1)))) { // 正字 + 異体字セレクタで3個分 return CLogicInt(3); } diff --git a/sakura_core/parse/CWordParse.cpp b/sakura_core/parse/CWordParse.cpp index b1f46c98d7..a09f7cf3d6 100644 --- a/sakura_core/parse/CWordParse.cpp +++ b/sakura_core/parse/CWordParse.cpp @@ -187,7 +187,7 @@ ECharKind CWordParse::WhatKindOfChar( } // IVS(正字 + 異体字セレクタ) else if (nCharChars == 3 && - IsVariationSelector(pData + nIdx + 1)) + IsVariationSelector(std::wstring_view(pData + nIdx + 1, pDataLen - (nIdx + 1)))) { ret = CK_ZEN_ETC; // 全角のその他(漢字など) } diff --git a/sakura_core/view/CTextMetrics.cpp b/sakura_core/view/CTextMetrics.cpp index 182c849031..9d225b3d15 100644 --- a/sakura_core/view/CTextMetrics.cpp +++ b/sakura_core/view/CTextMetrics.cpp @@ -109,7 +109,7 @@ const int* CTextMetrics::GenerateDxArray( vResultArray.push_back(cache.CalcPxWidthByFont(pText[i]) + spacing); nIndent += vResultArray.back(); - if (IsVariationSelector(pText + i + 1)) { + if (IsVariationSelector(std::wstring_view(pText + i + 1, nLength - (i + 1)))) { vResultArray.push_back(0); vResultArray.push_back(0); i += 2; diff --git a/tests/unittests/test-codechecker.cpp b/tests/unittests/test-codechecker.cpp index f7d84b1b01..1b5c2f9aa0 100644 --- a/tests/unittests/test-codechecker.cpp +++ b/tests/unittests/test-codechecker.cpp @@ -45,3 +45,24 @@ TEST(ConvertToUtf32, BinaryOnSurrogate) const auto& s = L"\xdcff"; EXPECT_EQ(0, ConvertToUtf32(s)); } + +TEST(IsVariationSelector, VariationSelectorCheck) +{ + // 異体字セレクタ開始 + const auto& vs1 = L"\U000E0100"; + EXPECT_TRUE(IsVariationSelector(vs1)); + + // 異体字セレクタ終了 + const auto& vs2 = L"\U000E01EF"; + EXPECT_TRUE(IsVariationSelector(vs2)); + + // 非該当文字列 + const auto& notvs1 = L""; + EXPECT_FALSE(IsVariationSelector(notvs1)); + const auto& notvs2 = L"\xDB40"; + EXPECT_FALSE(IsVariationSelector(notvs2)); + const auto& notvs3 = L"\U000E00FF"; + EXPECT_FALSE(IsVariationSelector(notvs3)); + const auto& notvs4 = L"\U000E01F0"; + EXPECT_FALSE(IsVariationSelector(notvs4)); +} diff --git a/tests/unittests/test-ctextmetrics.cpp b/tests/unittests/test-ctextmetrics.cpp index 4dfeee8970..1e0f2d0af8 100644 --- a/tests/unittests/test-ctextmetrics.cpp +++ b/tests/unittests/test-ctextmetrics.cpp @@ -225,7 +225,7 @@ TEST(CTextMetrics, GenerateDxArray8) // IVSのVariantSelectorが続く文字列は先頭1文字 + 幅0×2で生成する std::vector v; FakeCache1 cache; - CTextMetrics::GenerateDxArray(&v, L"葛󠄀", 2, 0, 0, 0, 10, cache); + CTextMetrics::GenerateDxArray(&v, L"葛󠄀", 3, 0, 0, 0, 10, cache); EXPECT_TRUE(v[0]); EXPECT_FALSE(v[1]); EXPECT_FALSE(v[2]);