diff --git a/intl/unicharutil/util/nsUnicharUtils.cpp b/intl/unicharutil/util/nsUnicharUtils.cpp index f82902f0fbf2..57c482841ecd 100644 --- a/intl/unicharutil/util/nsUnicharUtils.cpp +++ b/intl/unicharutil/util/nsUnicharUtils.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ @@ -425,4 +425,11 @@ HashUTF8AsUTF16(const char* aUTF8, uint32_t aLength, bool* aErr) return hash; } +bool +IsSegmentBreakSkipChar(uint32_t u) +{ + return unicode::IsEastAsianWidthFWH(u) && + unicode::GetScriptCode(u) != unicode::Script::HANGUL; +} + } // namespace mozilla diff --git a/intl/unicharutil/util/nsUnicharUtils.h b/intl/unicharutil/util/nsUnicharUtils.h index 86f201ca506f..e627720675e8 100644 --- a/intl/unicharutil/util/nsUnicharUtils.h +++ b/intl/unicharutil/util/nsUnicharUtils.h @@ -16,6 +16,8 @@ (0xf900u <= (u) && (u) <= 0xfaffu) || \ (0xff00u <= (u) && (u) <= 0xffefu) ) +#define IS_ZERO_WIDTH_SPACE(u) ((u) == 0x200B) + void ToLowerCase(nsAString&); void ToUpperCase(nsAString&); @@ -142,6 +144,9 @@ namespace mozilla { uint32_t HashUTF8AsUTF16(const char* aUTF8, uint32_t aLength, bool* aErr); +bool +IsSegmentBreakSkipChar(uint32_t u); + } // namespace mozilla #endif /* nsUnicharUtils_h__ */ diff --git a/layout/generic/nsTextFrameUtils.cpp b/layout/generic/nsTextFrameUtils.cpp index dc5f32e211a0..d07400f2bea3 100644 --- a/layout/generic/nsTextFrameUtils.cpp +++ b/layout/generic/nsTextFrameUtils.cpp @@ -5,11 +5,12 @@ #include "nsTextFrameUtils.h" -#include "nsUnicharUtils.h" #include "nsBidiUtils.h" +#include "nsCharTraits.h" #include "nsIContent.h" #include "nsStyleStruct.h" #include "nsTextFragment.h" +#include "nsUnicharUtils.h" #include static bool IsDiscardable(char16_t ch, uint32_t* aFlags) @@ -89,10 +90,31 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength, !IsSpaceCombiningSequenceTail(&aText[i + 1], aLength - (i + 1)))) { nowInWhitespace = true; } else if (ch == '\n' && aCompression == COMPRESS_WHITESPACE_NEWLINE) { - if (i > 0 && IS_CJ_CHAR(aText[i - 1]) && - i + 1 < aLength && IS_CJ_CHAR(aText[i + 1])) { - // Discard newlines between CJK chars. - // XXX this really requires more context to get right! + if ((i > 0 && IS_ZERO_WIDTH_SPACE(aText[i - 1])) || + (i + 1 < aLength && IS_ZERO_WIDTH_SPACE(aText[i + 1]))) { + aSkipChars->SkipChar(); + continue; + } + uint32_t ucs4before; + uint32_t ucs4after; + if (i > 1 && + NS_IS_LOW_SURROGATE(aText[i - 1]) && + NS_IS_HIGH_SURROGATE(aText[i - 2])) { + ucs4before = SURROGATE_TO_UCS4(aText[i - 2], aText[i - 1]); + } else if (i > 0) { + ucs4before = aText[i - 1]; + } + if (i + 2 < aLength && + NS_IS_HIGH_SURROGATE(aText[i + 1]) && + NS_IS_LOW_SURROGATE(aText[i + 2])) { + ucs4after = SURROGATE_TO_UCS4(aText[i + 1], aText[i + 2]); + } else if (i + 1 < aLength) { + ucs4after = aText[i + 1]; + } + if (i > 0 && IsSegmentBreakSkipChar(ucs4before) && + i + 1 < aLength && IsSegmentBreakSkipChar(ucs4after)) { + // Discard newlines between characters that have F, W, or H + // EastAsianWidth property and neither side is Hangul. aSkipChars->SkipChar(); continue; } diff --git a/layout/reftests/text/reftest.list b/layout/reftests/text/reftest.list index 7e3a8ced1be7..7e4bd55c02ce 100644 --- a/layout/reftests/text/reftest.list +++ b/layout/reftests/text/reftest.list @@ -338,3 +338,4 @@ HTTP(..) == space-font-1.html space-font-1-ref.html # handling of highly negative letter-spacing and intrinsic width == negative-letter-spacing-1.html negative-letter-spacing-1-ref.html +== segment-break-transformation-1.html segment-break-transformation-1-ref.html diff --git a/layout/reftests/text/segment-break-transformation-1-ref.html b/layout/reftests/text/segment-break-transformation-1-ref.html new file mode 100644 index 000000000000..dd11d683acff --- /dev/null +++ b/layout/reftests/text/segment-break-transformation-1-ref.html @@ -0,0 +1,34 @@ + + + + + + + + +
+

斷行測試 +

斷行測試 +

斷行測試 +

斷行測試 +

斷行測試 +

斷行
+測試
+

斷行
+測試
+

斷行
+測試
+

Hello Kitty +

HelloKitty +

HelloKitty +

HelloKitty + +

𠀀𠀁𠀂𠀃 +

𠀀測𠀂𠀃 +

𠀀𠀁測𠀃 +

+ + diff --git a/layout/reftests/text/segment-break-transformation-1.html b/layout/reftests/text/segment-break-transformation-1.html new file mode 100644 index 000000000000..8fe1f82d9090 --- /dev/null +++ b/layout/reftests/text/segment-break-transformation-1.html @@ -0,0 +1,50 @@ + + + + + + + + +
+

斷行 +測試 +

斷行​ +測試 +

斷行 +​測試 +

斷行​ +​測試 +

斷行 +測試 +

斷行 +測試 +

斷行 +測試 +

斷行 +測試 +

Hello +Kitty +

Hello​ +Kitty +

Hello +​Kitty +

Hello​ +​Kitty + +

𠀀𠀁 +𠀂𠀃 +

𠀀測 +𠀂𠀃 +

𠀀𠀁 +測𠀃 +

+ +