зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1011369 - Pass word-break and line-break properties to the line-breaker as two distinct enum class parameters. r=m_kato
Differential Revision: https://phabricator.services.mozilla.com/D30786 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
837368bc29
Коммит
9ac5b6c1af
|
@ -20,7 +20,8 @@ nsLineBreaker::nsLineBreaker()
|
|||
mCurrentWordContainsComplexChar(false),
|
||||
mAfterBreakableSpace(false),
|
||||
mBreakHere(false),
|
||||
mWordBreak(LineBreaker::kWordBreak_Normal) {}
|
||||
mWordBreak(LineBreaker::WordBreak::Normal),
|
||||
mStrictness(LineBreaker::Strictness::Auto) {}
|
||||
|
||||
nsLineBreaker::~nsLineBreaker() {
|
||||
NS_ASSERTION(mCurrentWord.Length() == 0,
|
||||
|
@ -57,22 +58,28 @@ static void SetupCapitalization(const char16_t* aWord, uint32_t aLength,
|
|||
nsresult nsLineBreaker::FlushCurrentWord() {
|
||||
uint32_t length = mCurrentWord.Length();
|
||||
AutoTArray<uint8_t, 4000> breakState;
|
||||
if (!breakState.AppendElements(length)) return NS_ERROR_OUT_OF_MEMORY;
|
||||
if (!breakState.AppendElements(length)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsTArray<bool> capitalizationState;
|
||||
|
||||
if (!mCurrentWordContainsComplexChar ||
|
||||
mWordBreak == LineBreaker::kWordBreak_Anywhere) {
|
||||
if (mStrictness == LineBreaker::Strictness::Anywhere) {
|
||||
memset(breakState.Elements(),
|
||||
gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL,
|
||||
length * sizeof(uint8_t));
|
||||
} else if (!mCurrentWordContainsComplexChar) {
|
||||
// For break-strict set everything internal to "break", otherwise
|
||||
// to "no break"!
|
||||
memset(breakState.Elements(),
|
||||
mWordBreak >= LineBreaker::kWordBreak_BreakAll
|
||||
mWordBreak == LineBreaker::WordBreak::BreakAll
|
||||
? gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL
|
||||
: gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE,
|
||||
length * sizeof(uint8_t));
|
||||
} else {
|
||||
nsContentUtils::LineBreaker()->GetJISx4051Breaks(
|
||||
mCurrentWord.Elements(), length, mWordBreak, breakState.Elements());
|
||||
mCurrentWord.Elements(), length, mWordBreak, mStrictness,
|
||||
breakState.Elements());
|
||||
}
|
||||
|
||||
bool autoHyphenate = mCurrentWordLanguage && !mCurrentWordContainsMixedLang;
|
||||
|
@ -226,7 +233,8 @@ nsresult nsLineBreaker::AppendText(nsAtom* aHyphenationLanguage,
|
|||
if (aSink && !noBreaksNeeded) {
|
||||
breakState[offset] =
|
||||
mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ||
|
||||
(mWordBreak >= LineBreaker::kWordBreak_BreakAll)
|
||||
mWordBreak == LineBreaker::WordBreak::BreakAll ||
|
||||
mStrictness == LineBreaker::Strictness::Anywhere
|
||||
? gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL
|
||||
: gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE;
|
||||
}
|
||||
|
@ -241,7 +249,7 @@ nsresult nsLineBreaker::AppendText(nsAtom* aHyphenationLanguage,
|
|||
// set it to false
|
||||
uint8_t currentStart = breakState[wordStart];
|
||||
nsContentUtils::LineBreaker()->GetJISx4051Breaks(
|
||||
aText + wordStart, offset - wordStart, mWordBreak,
|
||||
aText + wordStart, offset - wordStart, mWordBreak, mStrictness,
|
||||
breakState.Elements() + wordStart);
|
||||
breakState[wordStart] = currentStart;
|
||||
}
|
||||
|
@ -384,7 +392,8 @@ nsresult nsLineBreaker::AppendText(nsAtom* aHyphenationLanguage,
|
|||
// will be set by nsILineBreaker, we don't consider CJK at this point.
|
||||
breakState[offset] =
|
||||
mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ||
|
||||
(mWordBreak >= LineBreaker::kWordBreak_BreakAll)
|
||||
mWordBreak == LineBreaker::WordBreak::BreakAll ||
|
||||
mStrictness == LineBreaker::Strictness::Anywhere
|
||||
? gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL
|
||||
: gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE;
|
||||
}
|
||||
|
@ -398,7 +407,7 @@ nsresult nsLineBreaker::AppendText(nsAtom* aHyphenationLanguage,
|
|||
// set it to false
|
||||
uint8_t currentStart = breakState[wordStart];
|
||||
nsContentUtils::LineBreaker()->GetJISx4051Breaks(
|
||||
aText + wordStart, offset - wordStart, mWordBreak,
|
||||
aText + wordStart, offset - wordStart, mWordBreak, mStrictness,
|
||||
breakState.Elements() + wordStart);
|
||||
breakState[wordStart] = currentStart;
|
||||
}
|
||||
|
|
|
@ -175,9 +175,9 @@ class nsLineBreaker {
|
|||
|
||||
/*
|
||||
* Set word-break mode for linebreaker. This is set by word-break property.
|
||||
* @param aMode is LineBreaker::kWordBreak_* value.
|
||||
* @param aMode is LineBreaker::WordBreak::* value.
|
||||
*/
|
||||
void SetWordBreak(uint8_t aMode) {
|
||||
void SetWordBreak(mozilla::intl::LineBreaker::WordBreak aMode) {
|
||||
// If current word is non-empty and mode is changing, flush the breaker.
|
||||
if (aMode != mWordBreak && !mCurrentWord.IsEmpty()) {
|
||||
nsresult rv = FlushCurrentWord();
|
||||
|
@ -187,13 +187,32 @@ class nsLineBreaker {
|
|||
// If previous mode was break-all, we should allow a break here.
|
||||
// XXX (jfkthame) css-text spec seems unclear on this, raised question in
|
||||
// https://github.com/w3c/csswg-drafts/issues/3897
|
||||
if (mWordBreak == mozilla::intl::LineBreaker::kWordBreak_BreakAll) {
|
||||
if (mWordBreak == mozilla::intl::LineBreaker::WordBreak::BreakAll) {
|
||||
mBreakHere = true;
|
||||
}
|
||||
}
|
||||
mWordBreak = aMode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set line-break rule strictness mode for linebreaker. This is set by the
|
||||
* line-break property.
|
||||
* @param aMode is LineBreaker::Strictness::* value.
|
||||
*/
|
||||
void SetStrictness(mozilla::intl::LineBreaker::Strictness aMode) {
|
||||
if (aMode != mStrictness && !mCurrentWord.IsEmpty()) {
|
||||
nsresult rv = FlushCurrentWord();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("FlushCurrentWord failed, line-breaks may be wrong");
|
||||
}
|
||||
// If previous mode was anywhere, we should allow a break here.
|
||||
if (mStrictness == mozilla::intl::LineBreaker::Strictness::Anywhere) {
|
||||
mBreakHere = true;
|
||||
}
|
||||
}
|
||||
mStrictness = aMode;
|
||||
}
|
||||
|
||||
private:
|
||||
// This is a list of text sources that make up the "current word" (i.e.,
|
||||
// run of text which does not contain any whitespace). All the mLengths
|
||||
|
@ -239,7 +258,9 @@ class nsLineBreaker {
|
|||
// a run of breakable whitespace ends here
|
||||
bool mBreakHere;
|
||||
// line break mode by "word-break" style
|
||||
uint8_t mWordBreak;
|
||||
mozilla::intl::LineBreaker::WordBreak mWordBreak;
|
||||
// strictness of break rules, from line-break property
|
||||
mozilla::intl::LineBreaker::Strictness mStrictness;
|
||||
};
|
||||
|
||||
#endif /*NSLINEBREAKER_H_*/
|
||||
|
|
|
@ -824,8 +824,8 @@ int32_t LineBreaker::WordMove(const char16_t* aText, uint32_t aLen,
|
|||
ret = end;
|
||||
}
|
||||
} else {
|
||||
GetJISx4051Breaks(aText + begin, end - begin,
|
||||
LineBreaker::kWordBreak_Normal, breakState.Elements());
|
||||
GetJISx4051Breaks(aText + begin, end - begin, WordBreak::Normal,
|
||||
Strictness::Auto, breakState.Elements());
|
||||
|
||||
ret = aPos;
|
||||
do {
|
||||
|
@ -855,7 +855,8 @@ int32_t LineBreaker::Prev(const char16_t* aText, uint32_t aLen, uint32_t aPos) {
|
|||
}
|
||||
|
||||
void LineBreaker::GetJISx4051Breaks(const char16_t* aChars, uint32_t aLength,
|
||||
uint8_t aWordBreak, uint8_t* aBreakBefore) {
|
||||
WordBreak aWordBreak, Strictness aLevel,
|
||||
uint8_t* aBreakBefore) {
|
||||
uint32_t cur;
|
||||
int8_t lastClass = CLASS_NONE;
|
||||
ContextState state(aChars, aLength);
|
||||
|
@ -896,7 +897,7 @@ void LineBreaker::GetJISx4051Breaks(const char16_t* aChars, uint32_t aLength,
|
|||
// CLASS_CLOSE by GetClass(), but those classes also include others that
|
||||
// we don't want to touch here, so we re-check the Unicode line-break class
|
||||
// to determine which ones to modify.
|
||||
if (aWordBreak == LineBreaker::kWordBreak_BreakAll &&
|
||||
if (aWordBreak == WordBreak::BreakAll &&
|
||||
(cl == CLASS_CHARACTER || cl == CLASS_CLOSE)) {
|
||||
auto cls = GetLineBreakClass(ch);
|
||||
if (cls == U_LB_ALPHABETIC || cls == U_LB_NUMERIC ||
|
||||
|
@ -914,8 +915,8 @@ void LineBreaker::GetJISx4051Breaks(const char16_t* aChars, uint32_t aLength,
|
|||
if (cur > 0) {
|
||||
NS_ASSERTION(CLASS_COMPLEX != lastClass || CLASS_COMPLEX != cl,
|
||||
"Loop should have prevented adjacent complex chars here");
|
||||
if (aWordBreak == LineBreaker::kWordBreak_Normal ||
|
||||
aWordBreak == LineBreaker::kWordBreak_BreakAll) {
|
||||
if (aWordBreak == WordBreak::Normal ||
|
||||
aWordBreak == WordBreak::BreakAll) {
|
||||
allowBreak = (state.UseConservativeBreaking())
|
||||
? GetPairConservative(lastClass, cl)
|
||||
: GetPair(lastClass, cl);
|
||||
|
@ -938,7 +939,7 @@ void LineBreaker::GetJISx4051Breaks(const char16_t* aChars, uint32_t aLength,
|
|||
}
|
||||
}
|
||||
|
||||
if (aWordBreak == LineBreaker::kWordBreak_BreakAll) {
|
||||
if (aWordBreak == WordBreak::BreakAll) {
|
||||
// For break-all, we don't need to run a dictionary-based breaking
|
||||
// algorithm, we just allow breaks between all grapheme clusters.
|
||||
ClusterIterator ci(aChars + cur, end - cur);
|
||||
|
@ -967,7 +968,8 @@ void LineBreaker::GetJISx4051Breaks(const char16_t* aChars, uint32_t aLength,
|
|||
}
|
||||
|
||||
void LineBreaker::GetJISx4051Breaks(const uint8_t* aChars, uint32_t aLength,
|
||||
uint8_t aWordBreak, uint8_t* aBreakBefore) {
|
||||
WordBreak aWordBreak, Strictness aLevel,
|
||||
uint8_t* aBreakBefore) {
|
||||
uint32_t cur;
|
||||
int8_t lastClass = CLASS_NONE;
|
||||
ContextState state(aChars, aLength);
|
||||
|
@ -985,7 +987,7 @@ void LineBreaker::GetJISx4051Breaks(const uint8_t* aChars, uint32_t aLength,
|
|||
state.NotifyNonHyphenCharacter(ch);
|
||||
cl = GetClass(ch);
|
||||
}
|
||||
if (aWordBreak == LineBreaker::kWordBreak_BreakAll &&
|
||||
if (aWordBreak == WordBreak::BreakAll &&
|
||||
(cl == CLASS_CHARACTER || cl == CLASS_CLOSE)) {
|
||||
auto cls = GetLineBreakClass(ch);
|
||||
// Don't need to check additional Japanese/Korean classes in 8-bit
|
||||
|
@ -997,8 +999,8 @@ void LineBreaker::GetJISx4051Breaks(const uint8_t* aChars, uint32_t aLength,
|
|||
|
||||
bool allowBreak = false;
|
||||
if (cur > 0) {
|
||||
if (aWordBreak == LineBreaker::kWordBreak_Normal ||
|
||||
aWordBreak == LineBreaker::kWordBreak_BreakAll) {
|
||||
if (aWordBreak == WordBreak::Normal ||
|
||||
aWordBreak == WordBreak::BreakAll) {
|
||||
allowBreak = (state.UseConservativeBreaking())
|
||||
? GetPairConservative(lastClass, cl)
|
||||
: GetPair(lastClass, cl);
|
||||
|
|
|
@ -17,12 +17,18 @@ class LineBreaker {
|
|||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(LineBreaker)
|
||||
|
||||
enum {
|
||||
// Order is important here, because of tests for value >= BreakAll
|
||||
kWordBreak_Normal = 0, // default
|
||||
kWordBreak_KeepAll = 1, // always keep
|
||||
kWordBreak_BreakAll = 2, // break all
|
||||
kWordBreak_Anywhere = 3 // line-break:anywhere
|
||||
enum class WordBreak : uint8_t {
|
||||
Normal = 0, // default
|
||||
BreakAll = 1, // break all
|
||||
KeepAll = 2 // always keep
|
||||
};
|
||||
|
||||
enum class Strictness : uint8_t {
|
||||
Auto = 0,
|
||||
Loose = 1,
|
||||
Normal = 2,
|
||||
Strict = 3,
|
||||
Anywhere = 4
|
||||
};
|
||||
|
||||
static already_AddRefed<LineBreaker> Create();
|
||||
|
@ -38,9 +44,11 @@ class LineBreaker {
|
|||
// aLength is the length of the aText array and also the length of the
|
||||
// aBreakBefore output array.
|
||||
void GetJISx4051Breaks(const char16_t* aText, uint32_t aLength,
|
||||
uint8_t aWordBreak, uint8_t* aBreakBefore);
|
||||
WordBreak aWordBreak, Strictness aLevel,
|
||||
uint8_t* aBreakBefore);
|
||||
void GetJISx4051Breaks(const uint8_t* aText, uint32_t aLength,
|
||||
uint8_t aWordBreak, uint8_t* aBreakBefore);
|
||||
WordBreak aWordBreak, Strictness aLevel,
|
||||
uint8_t* aBreakBefore);
|
||||
|
||||
private:
|
||||
~LineBreaker() {}
|
||||
|
|
|
@ -2589,23 +2589,36 @@ void BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
|
|||
// each MappedFlow. The line-breaker will flush its text if the property
|
||||
// actually changes.
|
||||
const auto* styleText = mappedFlow->mStartFrame->StyleText();
|
||||
if (styleText->mLineBreak == StyleLineBreak::Anywhere) {
|
||||
mLineBreaker.SetWordBreak(LineBreaker::kWordBreak_Anywhere);
|
||||
} else {
|
||||
auto wordBreak = styleText->EffectiveWordBreak();
|
||||
switch (wordBreak) {
|
||||
case StyleWordBreak::BreakAll:
|
||||
mLineBreaker.SetWordBreak(LineBreaker::kWordBreak_BreakAll);
|
||||
break;
|
||||
case StyleWordBreak::KeepAll:
|
||||
mLineBreaker.SetWordBreak(LineBreaker::kWordBreak_KeepAll);
|
||||
break;
|
||||
case StyleWordBreak::Normal:
|
||||
default:
|
||||
MOZ_ASSERT(wordBreak == StyleWordBreak::Normal);
|
||||
mLineBreaker.SetWordBreak(LineBreaker::kWordBreak_Normal);
|
||||
break;
|
||||
}
|
||||
auto wordBreak = styleText->EffectiveWordBreak();
|
||||
switch (wordBreak) {
|
||||
case StyleWordBreak::BreakAll:
|
||||
mLineBreaker.SetWordBreak(LineBreaker::WordBreak::BreakAll);
|
||||
break;
|
||||
case StyleWordBreak::KeepAll:
|
||||
mLineBreaker.SetWordBreak(LineBreaker::WordBreak::KeepAll);
|
||||
break;
|
||||
case StyleWordBreak::Normal:
|
||||
default:
|
||||
MOZ_ASSERT(wordBreak == StyleWordBreak::Normal);
|
||||
mLineBreaker.SetWordBreak(LineBreaker::WordBreak::Normal);
|
||||
break;
|
||||
}
|
||||
switch (styleText->mLineBreak) {
|
||||
case StyleLineBreak::Auto:
|
||||
mLineBreaker.SetStrictness(LineBreaker::Strictness::Auto);
|
||||
break;
|
||||
case StyleLineBreak::Normal:
|
||||
mLineBreaker.SetStrictness(LineBreaker::Strictness::Normal);
|
||||
break;
|
||||
case StyleLineBreak::Loose:
|
||||
mLineBreaker.SetStrictness(LineBreaker::Strictness::Loose);
|
||||
break;
|
||||
case StyleLineBreak::Strict:
|
||||
mLineBreaker.SetStrictness(LineBreaker::Strictness::Strict);
|
||||
break;
|
||||
case StyleLineBreak::Anywhere:
|
||||
mLineBreaker.SetStrictness(LineBreaker::Strictness::Anywhere);
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t offset = iter.GetSkippedOffset();
|
||||
|
|
Загрузка…
Ссылка в новой задаче