Bug 1316482 - use the refactored TransformText as a template function for both char16_t and uint8_t text. r=xidorn

With this patch, we shall only maintain one version of the TransformText logic.

MozReview-Commit-ID: JAIksFVqvqf

--HG--
extra : rebase_source : 49ec749ae74f872e9749e026affe7f2e22db71f9
This commit is contained in:
Jeremy Chen 2017-01-10 00:02:03 +08:00
Родитель 7b8e25751d
Коммит f53d660a40
2 изменённых файлов: 48 добавлений и 101 удалений

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

@ -56,12 +56,13 @@ IsSpaceOrTabOrSegmentBreak(char16_t aCh)
return IsSpaceOrTab(aCh) || IsSegmentBreak(aCh); return IsSpaceOrTab(aCh) || IsSegmentBreak(aCh);
} }
static char16_t* template<class CharT>
TransformWhiteSpaces(const char16_t* aText, uint32_t aLength, static CharT*
TransformWhiteSpaces(const CharT* aText, uint32_t aLength,
uint32_t aBegin, uint32_t aEnd, uint32_t aBegin, uint32_t aEnd,
bool aHasSegmentBreak, bool aHasSegmentBreak,
bool& aInWhitespace, bool& aInWhitespace,
char16_t* aOutput, CharT* aOutput,
uint32_t& aFlags, uint32_t& aFlags,
nsTextFrameUtils::CompressionMode aCompression, nsTextFrameUtils::CompressionMode aCompression,
gfxSkipChars* aSkipChars) gfxSkipChars* aSkipChars)
@ -70,10 +71,14 @@ TransformWhiteSpaces(const char16_t* aText, uint32_t aLength,
aCompression == nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE, aCompression == nsTextFrameUtils::COMPRESS_WHITESPACE_NEWLINE,
"whitespaces should be skippable!!"); "whitespaces should be skippable!!");
// Get the context preceding/following this white space range. // Get the context preceding/following this white space range.
// For 8-bit text (sizeof CharT == 1), the checks here should get optimized
// out, and isSegmentBreakSkippable should be initialized to be 'false'.
bool isSegmentBreakSkippable = bool isSegmentBreakSkippable =
(aBegin > 0 && IS_ZERO_WIDTH_SPACE(aText[aBegin - 1])) || sizeof(CharT) > 1 &&
(aEnd < aLength && IS_ZERO_WIDTH_SPACE(aText[aEnd])); ((aBegin > 0 && IS_ZERO_WIDTH_SPACE(aText[aBegin - 1])) ||
if (!isSegmentBreakSkippable && aBegin > 0 && aEnd < aLength) { (aEnd < aLength && IS_ZERO_WIDTH_SPACE(aText[aEnd])));
if (sizeof(CharT) > 1 && !isSegmentBreakSkippable &&
aBegin > 0 && aEnd < aLength) {
uint32_t ucs4before; uint32_t ucs4before;
uint32_t ucs4after; uint32_t ucs4after;
if (aBegin > 1 && if (aBegin > 1 &&
@ -97,7 +102,7 @@ TransformWhiteSpaces(const char16_t* aText, uint32_t aLength,
} }
for (uint32_t i = aBegin; i < aEnd; ++i) { for (uint32_t i = aBegin; i < aEnd; ++i) {
char16_t ch = aText[i]; CharT ch = aText[i];
bool keepChar = false; bool keepChar = false;
bool keepTransformedWhiteSpace = false; bool keepTransformedWhiteSpace = false;
if (IsDiscardable(ch, &aFlags)) { if (IsDiscardable(ch, &aFlags)) {
@ -167,16 +172,17 @@ TransformWhiteSpaces(const char16_t* aText, uint32_t aLength,
return aOutput; return aOutput;
} }
char16_t* template<class CharT>
nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength, CharT*
char16_t* aOutput, nsTextFrameUtils::TransformText(const CharT* aText, uint32_t aLength,
CharT* aOutput,
CompressionMode aCompression, CompressionMode aCompression,
uint8_t* aIncomingFlags, uint8_t* aIncomingFlags,
gfxSkipChars* aSkipChars, gfxSkipChars* aSkipChars,
uint32_t* aAnalysisFlags) uint32_t* aAnalysisFlags)
{ {
uint32_t flags = 0; uint32_t flags = 0;
char16_t* outputStart = aOutput; CharT* outputStart = aOutput;
bool lastCharArabic = false; bool lastCharArabic = false;
if (aCompression == COMPRESS_NONE || if (aCompression == COMPRESS_NONE ||
@ -184,7 +190,7 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
// Skip discardables. // Skip discardables.
uint32_t i; uint32_t i;
for (i = 0; i < aLength; ++i) { for (i = 0; i < aLength; ++i) {
char16_t ch = aText[i]; CharT ch = aText[i];
if (IsDiscardable(ch, &flags)) { if (IsDiscardable(ch, &flags)) {
aSkipChars->SkipChar(); aSkipChars->SkipChar();
} else { } else {
@ -215,7 +221,7 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
bool inWhitespace = (*aIncomingFlags & INCOMING_WHITESPACE) != 0; bool inWhitespace = (*aIncomingFlags & INCOMING_WHITESPACE) != 0;
uint32_t i; uint32_t i;
for (i = 0; i < aLength; ++i) { for (i = 0; i < aLength; ++i) {
char16_t ch = aText[i]; CharT ch = aText[i];
// CSS Text 3 - 4.1. The White Space Processing Rules // CSS Text 3 - 4.1. The White Space Processing Rules
// White space processing in CSS affects only the document white space // White space processing in CSS affects only the document white space
// characters: spaces (U+0020), tabs (U+0009), and segment breaks. // characters: spaces (U+0020), tabs (U+0009), and segment breaks.
@ -244,7 +250,7 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
} }
// If the last white space is followed by a combining sequence tail, // If the last white space is followed by a combining sequence tail,
// exclude it from the range of TransformWhiteSpaces. // exclude it from the range of TransformWhiteSpaces.
if (aText[j - 1] == ' ' && j < aLength && if (sizeof(CharT) > 1 && aText[j - 1] == ' ' && j < aLength &&
IsSpaceCombiningSequenceTail(&aText[j], aLength - j)) { IsSpaceCombiningSequenceTail(&aText[j], aLength - j)) {
keepLastSpace = true; keepLastSpace = true;
j--; j--;
@ -299,85 +305,28 @@ nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
*aAnalysisFlags = flags; *aAnalysisFlags = flags;
return aOutput; return aOutput;
} }
/*
uint8_t* * NOTE: This template is part of public API of nsTextFrameUtils, while
* its function body is not available in the header. It may stop working
* (fail to resolve symbol in link time) once its callsites are moved to a
* different translation unit (e.g. a different unified source file).
* Explicit instantiating this function template with `uint8_t` and `char16_t`
* could prevent us from the potential risk.
*/
template uint8_t*
nsTextFrameUtils::TransformText(const uint8_t* aText, uint32_t aLength, nsTextFrameUtils::TransformText(const uint8_t* aText, uint32_t aLength,
uint8_t* aOutput, uint8_t* aOutput,
CompressionMode aCompression, CompressionMode aCompression,
uint8_t* aIncomingFlags, uint8_t* aIncomingFlags,
gfxSkipChars* aSkipChars, gfxSkipChars* aSkipChars,
uint32_t* aAnalysisFlags) uint32_t* aAnalysisFlags);
{ template char16_t*
uint32_t flags = 0; nsTextFrameUtils::TransformText(const char16_t* aText, uint32_t aLength,
uint8_t* outputStart = aOutput; char16_t* aOutput,
CompressionMode aCompression,
if (aCompression == COMPRESS_NONE || uint8_t* aIncomingFlags,
aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) { gfxSkipChars* aSkipChars,
// Skip discardables. uint32_t* aAnalysisFlags);
uint32_t i;
for (i = 0; i < aLength; ++i) {
uint8_t ch = aText[i];
if (IsDiscardable(ch, &flags)) {
aSkipChars->SkipChar();
} else {
aSkipChars->KeepChar();
if (aCompression == COMPRESS_NONE_TRANSFORM_TO_SPACE) {
if (ch == '\t' || ch == '\n') {
ch = ' ';
flags |= TEXT_WAS_TRANSFORMED;
}
} else {
// aCompression == COMPRESS_NONE
if (ch == '\t') {
flags |= TEXT_HAS_TAB;
}
}
*aOutput++ = ch;
}
}
*aIncomingFlags &= ~(INCOMING_ARABICCHAR | INCOMING_WHITESPACE);
} else {
bool inWhitespace = (*aIncomingFlags & INCOMING_WHITESPACE) != 0;
uint32_t i;
for (i = 0; i < aLength; ++i) {
uint8_t ch = aText[i];
bool nowInWhitespace = ch == ' ' || ch == '\t' ||
(ch == '\n' && aCompression == COMPRESS_WHITESPACE_NEWLINE);
if (!nowInWhitespace) {
if (IsDiscardable(ch, &flags)) {
aSkipChars->SkipChar();
nowInWhitespace = inWhitespace;
} else {
*aOutput++ = ch;
aSkipChars->KeepChar();
}
} else {
if (inWhitespace) {
aSkipChars->SkipChar();
} else {
if (ch != ' ') {
flags |= TEXT_WAS_TRANSFORMED;
}
*aOutput++ = ' ';
aSkipChars->KeepChar();
}
}
inWhitespace = nowInWhitespace;
}
*aIncomingFlags &= ~INCOMING_ARABICCHAR;
if (inWhitespace) {
*aIncomingFlags |= INCOMING_WHITESPACE;
} else {
*aIncomingFlags &= ~INCOMING_WHITESPACE;
}
}
if (outputStart + aLength != aOutput) {
flags |= TEXT_WAS_TRANSFORMED;
}
*aAnalysisFlags = flags;
return aOutput;
}
uint32_t uint32_t
nsTextFrameUtils::ComputeApproximateLengthWithWhitespaceCompression( nsTextFrameUtils::ComputeApproximateLengthWithWhitespaceCompression(

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

@ -87,6 +87,10 @@ public:
) )
); );
} }
static bool
IsSpaceCombiningSequenceTail(const uint8_t* aChars, int32_t aLength) {
return false;
}
enum CompressionMode { enum CompressionMode {
COMPRESS_NONE, COMPRESS_NONE,
@ -109,19 +113,13 @@ public:
* or an Arabic character preceding this text. We set it to indicate if * or an Arabic character preceding this text. We set it to indicate if
* there's an Arabic character or whitespace preceding the end of this text. * there's an Arabic character or whitespace preceding the end of this text.
*/ */
static char16_t* TransformText(const char16_t* aText, uint32_t aLength, template<class CharT>
char16_t* aOutput, static CharT* TransformText(const CharT* aText, uint32_t aLength,
CompressionMode aCompression, CharT* aOutput,
uint8_t* aIncomingFlags, CompressionMode aCompression,
gfxSkipChars* aSkipChars, uint8_t* aIncomingFlags,
uint32_t* aAnalysisFlags); gfxSkipChars* aSkipChars,
uint32_t* aAnalysisFlags);
static uint8_t* TransformText(const uint8_t* aText, uint32_t aLength,
uint8_t* aOutput,
CompressionMode aCompression,
uint8_t* aIncomingFlags,
gfxSkipChars* aSkipChars,
uint32_t* aAnalysisFlags);
static void static void
AppendLineBreakOffset(nsTArray<uint32_t>* aArray, uint32_t aOffset) AppendLineBreakOffset(nsTArray<uint32_t>* aArray, uint32_t aOffset)