Bug 249159 - Part 1 Add word-break interface to nsILineBreaker. r=smontagu

This commit is contained in:
Makoto Kato 2012-05-07 12:18:23 -07:00
Родитель d40cb45268
Коммит 6d5b05da76
5 изменённых файлов: 62 добавлений и 23 удалений

Просмотреть файл

@ -201,6 +201,12 @@ public:
*/ */
nsresult Reset(bool* aTrailingBreak); 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: private:
// This is a list of text sources that make up the "current word" (i.e., // 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 // 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 // True if a break must be allowed at the current position because
// a run of breakable whitespace ends here // a run of breakable whitespace ends here
bool mBreakHere; bool mBreakHere;
// line break mode by "word-break" style
PRUint8 mWordBreak;
}; };
#endif /*NSLINEBREAKER_H_*/ #endif /*NSLINEBREAKER_H_*/

Просмотреть файл

@ -47,7 +47,8 @@ nsLineBreaker::nsLineBreaker()
: mCurrentWordLangGroup(nsnull), : mCurrentWordLangGroup(nsnull),
mCurrentWordContainsMixedLang(false), mCurrentWordContainsMixedLang(false),
mCurrentWordContainsComplexChar(false), mCurrentWordContainsComplexChar(false),
mAfterBreakableSpace(false), mBreakHere(false) mAfterBreakableSpace(false), mBreakHere(false),
mWordBreak(nsILineBreaker::kWordBreak_Normal)
{ {
} }
@ -96,13 +97,17 @@ nsLineBreaker::FlushCurrentWord()
nsTArray<bool> capitalizationState; nsTArray<bool> capitalizationState;
if (!mCurrentWordContainsComplexChar) { if (!mCurrentWordContainsComplexChar) {
// Just set everything internal to "no break"! // For break-strict set everything internal to "break", otherwise
// to "no break"!
memset(breakState.Elements(), 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)); length*sizeof(PRUint8));
} else { } else {
nsContentUtils::LineBreaker()-> nsContentUtils::LineBreaker()->
GetJISx4051Breaks(mCurrentWord.Elements(), length, breakState.Elements()); GetJISx4051Breaks(mCurrentWord.Elements(), length, mWordBreak,
breakState.Elements());
} }
bool autoHyphenate = mCurrentWordLangGroup && bool autoHyphenate = mCurrentWordLangGroup &&
@ -266,6 +271,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUnichar* aText, PRUint32
PRUint8 currentStart = breakState[wordStart]; PRUint8 currentStart = breakState[wordStart];
nsContentUtils::LineBreaker()-> nsContentUtils::LineBreaker()->
GetJISx4051Breaks(aText + wordStart, offset - wordStart, GetJISx4051Breaks(aText + wordStart, offset - wordStart,
mWordBreak,
breakState.Elements() + wordStart); breakState.Elements() + wordStart);
breakState[wordStart] = currentStart; breakState[wordStart] = currentStart;
} }
@ -411,8 +417,11 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL
bool isBreakableSpace = isSpace && !(aFlags & BREAK_SUPPRESS_INSIDE); bool isBreakableSpace = isSpace && !(aFlags & BREAK_SUPPRESS_INSIDE);
if (aSink) { 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] = breakState[offset] =
mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ? mBreakHere || (mAfterBreakableSpace && !isBreakableSpace) ||
(mWordBreak == nsILineBreaker::kWordBreak_BreakAll) ?
gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL : gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NORMAL :
gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE; gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_NONE;
} }
@ -427,6 +436,7 @@ nsLineBreaker::AppendText(nsIAtom* aLangGroup, const PRUint8* aText, PRUint32 aL
PRUint8 currentStart = breakState[wordStart]; PRUint8 currentStart = breakState[wordStart];
nsContentUtils::LineBreaker()-> nsContentUtils::LineBreaker()->
GetJISx4051Breaks(aText + wordStart, offset - wordStart, GetJISx4051Breaks(aText + wordStart, offset - wordStart,
mWordBreak,
breakState.Elements() + wordStart); breakState.Elements() + wordStart);
breakState[wordStart] = currentStart; breakState[wordStart] = currentStart;
} }

Просмотреть файл

@ -43,15 +43,22 @@
#define NS_LINEBREAKER_NEED_MORE_TEXT -1 #define NS_LINEBREAKER_NEED_MORE_TEXT -1
// {5ae68851-d9a3-49fd-9388-58586dad8044} // {0x4b0b9e04-6ffb-4647-aa5f-2fa2ebd883e8}
#define NS_ILINEBREAKER_IID \ #define NS_ILINEBREAKER_IID \
{ 0x5ae68851, 0xd9a3, 0x49fd, \ {0x4b0b9e04, 0x6ffb, 0x4647, \
{ 0x93, 0x88, 0x58, 0x58, 0x6d, 0xad, 0x80, 0x44 } } {0xaa, 0x5f, 0x2f, 0xa2, 0xeb, 0xd8, 0x83, 0xe8}}
class nsILineBreaker : public nsISupports class nsILineBreaker : public nsISupports
{ {
public: public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILINEBREAKER_IID) 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, virtual PRInt32 Next( const PRUnichar* aText, PRUint32 aLen,
PRUint32 aPos) = 0; PRUint32 aPos) = 0;
@ -65,8 +72,10 @@ public:
// aLength is the length of the aText array and also the length of the aBreakBefore // aLength is the length of the aText array and also the length of the aBreakBefore
// output array. // output array.
virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength, virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength,
PRUint8 aWordBreak,
PRUint8* aBreakBefore) = 0; PRUint8* aBreakBefore) = 0;
virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength, virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength,
PRUint8 aWordBreak,
PRUint8* aBreakBefore) = 0; PRUint8* aBreakBefore) = 0;
}; };

Просмотреть файл

@ -797,7 +797,8 @@ nsJISx4051LineBreaker::WordMove(const PRUnichar* aText, PRUint32 aLen,
ret = end; ret = end;
} }
} else { } else {
GetJISx4051Breaks(aText + begin, end - begin, breakState.Elements()); GetJISx4051Breaks(aText + begin, end - begin, nsILineBreaker::kWordBreak_Normal,
breakState.Elements());
ret = aPos; ret = aPos;
do { do {
@ -833,6 +834,7 @@ nsJISx4051LineBreaker::Prev(const PRUnichar* aText, PRUint32 aLen,
void void
nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLength, nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLength,
PRUint8 aWordBreak,
PRUint8* aBreakBefore) PRUint8* aBreakBefore)
{ {
PRUint32 cur; PRUint32 cur;
@ -855,16 +857,16 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng
cl = GetClass(ch); cl = GetClass(ch);
} }
bool allowBreak; bool allowBreak = false;
if (cur > 0) { if (cur > 0) {
NS_ASSERTION(CLASS_COMPLEX != lastClass || CLASS_COMPLEX != cl, NS_ASSERTION(CLASS_COMPLEX != lastClass || CLASS_COMPLEX != cl,
"Loop should have prevented adjacent complex chars here"); "Loop should have prevented adjacent complex chars here");
if (state.UseConservativeBreaking()) if (aWordBreak == nsILineBreaker::kWordBreak_Normal) {
allowBreak = GetPairConservative(lastClass, cl); allowBreak = (state.UseConservativeBreaking()) ?
else GetPairConservative(lastClass, cl) : GetPair(lastClass, cl);
allowBreak = GetPair(lastClass, cl); } else if (aWordBreak == nsILineBreaker::kWordBreak_BreakAll) {
} else { allowBreak = true;
allowBreak = false; }
} }
aBreakBefore[cur] = allowBreak; aBreakBefore[cur] = allowBreak;
if (allowBreak) if (allowBreak)
@ -879,6 +881,13 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng
NS_GetComplexLineBreaks(aChars + cur, end - cur, aBreakBefore + cur); 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 // restore breakability at chunk begin, which was always set to false
// by the complex line breaker // by the complex line breaker
aBreakBefore[cur] = allowBreak; aBreakBefore[cur] = allowBreak;
@ -890,6 +899,7 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng
void void
nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength, nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength,
PRUint8 aWordBreak,
PRUint8* aBreakBefore) PRUint8* aBreakBefore)
{ {
PRUint32 cur; PRUint32 cur;
@ -912,14 +922,14 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength
cl = GetClass(ch); cl = GetClass(ch);
} }
bool allowBreak; bool allowBreak = false;
if (cur > 0) { if (cur > 0) {
if (state.UseConservativeBreaking()) if (aWordBreak == nsILineBreaker::kWordBreak_Normal) {
allowBreak = GetPairConservative(lastClass, cl); allowBreak = (state.UseConservativeBreaking()) ?
else GetPairConservative(lastClass, cl) : GetPair(lastClass, cl);
allowBreak = GetPair(lastClass, cl); } else if (aWordBreak == nsILineBreaker::kWordBreak_BreakAll) {
} else { allowBreak = true;
allowBreak = false; }
} }
aBreakBefore[cur] = allowBreak; aBreakBefore[cur] = allowBreak;
if (allowBreak) if (allowBreak)

Просмотреть файл

@ -53,8 +53,10 @@ public:
PRInt32 Prev( const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos); PRInt32 Prev( const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos);
virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength, virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength,
PRUint8 aBreakMode,
PRUint8* aBreakBefore); PRUint8* aBreakBefore);
virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength, virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength,
PRUint8 aBreakMode,
PRUint8* aBreakBefore); PRUint8* aBreakBefore);
private: private: