From 6d5b05da7666a08bba2bcce0ba67ca953b4fef30 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Mon, 7 May 2012 12:18:23 -0700 Subject: [PATCH] Bug 249159 - Part 1 Add word-break interface to nsILineBreaker. r=smontagu --- content/base/public/nsLineBreaker.h | 8 +++++ content/base/src/nsLineBreaker.cpp | 20 +++++++++--- intl/lwbrk/public/nsILineBreaker.h | 15 +++++++-- intl/lwbrk/src/nsJISx4501LineBreaker.cpp | 40 +++++++++++++++--------- intl/lwbrk/src/nsJISx4501LineBreaker.h | 2 ++ 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/content/base/public/nsLineBreaker.h b/content/base/public/nsLineBreaker.h index ff15e247db2..293a61053a8 100644 --- a/content/base/public/nsLineBreaker.h +++ b/content/base/public/nsLineBreaker.h @@ -201,6 +201,12 @@ public: */ nsresult Reset(bool* aTrailingBreak); + /* + * Set word-break mode for linebreaker. This is set by word-break property. + * @param aMode is nsILineBreaker::kWordBreak_* value. + */ + void SetWordBreak(PRUint8 aMode) { mWordBreak = 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 @@ -243,6 +249,8 @@ private: // True if a break must be allowed at the current position because // a run of breakable whitespace ends here bool mBreakHere; + // line break mode by "word-break" style + PRUint8 mWordBreak; }; #endif /*NSLINEBREAKER_H_*/ diff --git a/content/base/src/nsLineBreaker.cpp b/content/base/src/nsLineBreaker.cpp index 82190f07306..dda0587c45c 100644 --- a/content/base/src/nsLineBreaker.cpp +++ b/content/base/src/nsLineBreaker.cpp @@ -47,7 +47,8 @@ nsLineBreaker::nsLineBreaker() : mCurrentWordLangGroup(nsnull), mCurrentWordContainsMixedLang(false), mCurrentWordContainsComplexChar(false), - mAfterBreakableSpace(false), mBreakHere(false) + mAfterBreakableSpace(false), mBreakHere(false), + mWordBreak(nsILineBreaker::kWordBreak_Normal) { } @@ -96,13 +97,17 @@ nsLineBreaker::FlushCurrentWord() nsTArray capitalizationState; if (!mCurrentWordContainsComplexChar) { - // Just set everything internal to "no break"! + // For break-strict set everything internal to "break", otherwise + // to "no break"! memset(breakState.Elements(), - gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE, + mWordBreak == nsILineBreaker::kWordBreak_BreakAll ? + gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL : + gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE, length*sizeof(PRUint8)); } else { nsContentUtils::LineBreaker()-> - GetJISx4051Breaks(mCurrentWord.Elements(), length, breakState.Elements()); + GetJISx4051Breaks(mCurrentWord.Elements(), length, mWordBreak, + breakState.Elements()); } bool autoHyphenate = mCurrentWordLangGroup && @@ -266,6 +271,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32 PRUint8 currentStart = breakState[wordStart]; nsContentUtils::LineBreaker()-> GetJISx4051Breaks(aText + wordStart, offset - wordStart, + mWordBreak, breakState.Elements() + wordStart); breakState[wordStart] = currentStart; } @@ -411,8 +417,11 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL bool isBreakableSpace = isSpace && !(aFlags & BREAK_SUPPRESS_INSIDE); if (aSink) { + // Consider word-break style. Since the break position of CJK scripts + // will be set by nsILineBreaker, we don't consider CJK at this point. breakState[offset] = - mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ? + mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) || + (mWordBreak == nsILineBreaker::kWordBreak_BreakAll) ? gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL : gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE; } @@ -427,6 +436,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL PRUint8 currentStart = breakState[wordStart]; nsContentUtils::LineBreaker()-> GetJISx4051Breaks(aText + wordStart, offset - wordStart, + mWordBreak, breakState.Elements() + wordStart); breakState[wordStart] = currentStart; } diff --git a/intl/lwbrk/public/nsILineBreaker.h b/intl/lwbrk/public/nsILineBreaker.h index 43ebd40a81b..c412d9de4bc 100644 --- a/intl/lwbrk/public/nsILineBreaker.h +++ b/intl/lwbrk/public/nsILineBreaker.h @@ -43,15 +43,22 @@ #define NS_LINEBREAKER_NEED_MORE_TEXT -1 -// {5ae68851-d9a3-49fd-9388-58586dad8044} +// {0x4b0b9e04-6ffb-4647-aa5f-2fa2ebd883e8} #define NS_ILINEBREAKER_IID \ -{ 0x5ae68851, 0xd9a3, 0x49fd, \ - { 0x93, 0x88, 0x58, 0x58, 0x6d, 0xad, 0x80, 0x44 } } +{0x4b0b9e04, 0x6ffb, 0x4647, \ + {0xaa, 0x5f, 0x2f, 0xa2, 0xeb, 0xd8, 0x83, 0xe8}} class nsILineBreaker : public nsISupports { public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILINEBREAKER_IID) + + enum { + kWordBreak_Normal = 0, // default + kWordBreak_BreakAll = 1, // break all + kWordBreak_KeepAll = 2 // always keep + }; + virtual PRInt32 Next( const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos) = 0; @@ -65,8 +72,10 @@ public: // aLength is the length of the aText array and also the length of the aBreakBefore // output array. virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength, + PRUint8 aWordBreak, PRUint8* aBreakBefore) = 0; virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength, + PRUint8 aWordBreak, PRUint8* aBreakBefore) = 0; }; diff --git a/intl/lwbrk/src/nsJISx4501LineBreaker.cpp b/intl/lwbrk/src/nsJISx4501LineBreaker.cpp index f6e98e71027..352ff6acbfd 100644 --- a/intl/lwbrk/src/nsJISx4501LineBreaker.cpp +++ b/intl/lwbrk/src/nsJISx4501LineBreaker.cpp @@ -797,7 +797,8 @@ nsJISx4051LineBreaker::WordMove(const PRUnichar* aText, PRUint32 aLen, ret = end; } } else { - GetJISx4051Breaks(aText + begin, end - begin, breakState.Elements()); + GetJISx4051Breaks(aText + begin, end - begin, nsILineBreaker::kWordBreak_Normal, + breakState.Elements()); ret = aPos; do { @@ -833,6 +834,7 @@ nsJISx4051LineBreaker::Prev(const PRUnichar* aText, PRUint32 aLen, void nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLength, + PRUint8 aWordBreak, PRUint8* aBreakBefore) { PRUint32 cur; @@ -855,16 +857,16 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng cl = GetClass(ch); } - bool allowBreak; + bool allowBreak = false; if (cur > 0) { NS_ASSERTION(CLASS_COMPLEX != lastClass || CLASS_COMPLEX != cl, "Loop should have prevented adjacent complex chars here"); - if (state.UseConservativeBreaking()) - allowBreak = GetPairConservative(lastClass, cl); - else - allowBreak = GetPair(lastClass, cl); - } else { - allowBreak = false; + if (aWordBreak == nsILineBreaker::kWordBreak_Normal) { + allowBreak = (state.UseConservativeBreaking()) ? + GetPairConservative(lastClass, cl) : GetPair(lastClass, cl); + } else if (aWordBreak == nsILineBreaker::kWordBreak_BreakAll) { + allowBreak = true; + } } aBreakBefore[cur] = allowBreak; if (allowBreak) @@ -879,6 +881,13 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng NS_GetComplexLineBreaks(aChars + cur, end - cur, aBreakBefore + cur); + // We have to consider word-break value again for complex characters + if (aWordBreak != nsILineBreaker::kWordBreak_Normal) { + // Respect word-break property + for (PRUint32 i = cur; i < end; i++) + aBreakBefore[i] = (aWordBreak == nsILineBreaker::kWordBreak_BreakAll); + } + // restore breakability at chunk begin, which was always set to false // by the complex line breaker aBreakBefore[cur] = allowBreak; @@ -890,6 +899,7 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng void nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength, + PRUint8 aWordBreak, PRUint8* aBreakBefore) { PRUint32 cur; @@ -912,14 +922,14 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength cl = GetClass(ch); } - bool allowBreak; + bool allowBreak = false; if (cur > 0) { - if (state.UseConservativeBreaking()) - allowBreak = GetPairConservative(lastClass, cl); - else - allowBreak = GetPair(lastClass, cl); - } else { - allowBreak = false; + if (aWordBreak == nsILineBreaker::kWordBreak_Normal) { + allowBreak = (state.UseConservativeBreaking()) ? + GetPairConservative(lastClass, cl) : GetPair(lastClass, cl); + } else if (aWordBreak == nsILineBreaker::kWordBreak_BreakAll) { + allowBreak = true; + } } aBreakBefore[cur] = allowBreak; if (allowBreak) diff --git a/intl/lwbrk/src/nsJISx4501LineBreaker.h b/intl/lwbrk/src/nsJISx4501LineBreaker.h index 71142052b04..dcd2b22cb8e 100644 --- a/intl/lwbrk/src/nsJISx4501LineBreaker.h +++ b/intl/lwbrk/src/nsJISx4501LineBreaker.h @@ -53,8 +53,10 @@ public: PRInt32 Prev( const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos); virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength, + PRUint8 aBreakMode, PRUint8* aBreakBefore); virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength, + PRUint8 aBreakMode, PRUint8* aBreakBefore); private: