зеркало из https://github.com/mozilla/gecko-dev.git
Bug 264412. Optimize GetRenderedText. r=mats
With these changes we're slightly faster than Chrome on the non-reflowing part of Olli's testcase. --HG-- extra : commitid : 75liwqsBeJY extra : rebase_source : 34ee5d1fdfbb3b9d2ef8945f78ded935debb9106
This commit is contained in:
Родитель
7c373233ed
Коммит
00af2dcc78
|
@ -3396,36 +3396,38 @@ nsRange::GetInnerTextNoFlush(DOMString& aValue, ErrorResult& aError,
|
|||
nsIContent* child = currentNode->GetFirstChild();
|
||||
if (child) {
|
||||
currentNode = child;
|
||||
} else {
|
||||
currentState = AFTER_NODE;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (isVisibleAndNotReplaced) {
|
||||
if (currentNode->IsHTMLElement(nsGkAtoms::br)) {
|
||||
currentState = AFTER_NODE;
|
||||
}
|
||||
if (currentNode == endNode && currentState == endState) {
|
||||
break;
|
||||
}
|
||||
if (isVisibleAndNotReplaced) {
|
||||
if (currentNode->IsHTMLElement(nsGkAtoms::br)) {
|
||||
result.Append('\n');
|
||||
}
|
||||
switch (f->StyleDisplay()->mDisplay) {
|
||||
case NS_STYLE_DISPLAY_TABLE_CELL:
|
||||
if (!IsLastCellOfRow(f)) {
|
||||
result.Append('\t');
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_TABLE_ROW:
|
||||
if (!IsLastRowOfRowGroup(f) ||
|
||||
!IsLastNonemptyRowGroupOfTable(f->GetParent())) {
|
||||
result.Append('\n');
|
||||
}
|
||||
switch (f->StyleDisplay()->mDisplay) {
|
||||
case NS_STYLE_DISPLAY_TABLE_CELL:
|
||||
if (!IsLastCellOfRow(f)) {
|
||||
result.Append('\t');
|
||||
}
|
||||
break;
|
||||
case NS_STYLE_DISPLAY_TABLE_ROW:
|
||||
if (!IsLastRowOfRowGroup(f) ||
|
||||
!IsLastNonemptyRowGroupOfTable(f->GetParent())) {
|
||||
result.Append('\n');
|
||||
}
|
||||
break;
|
||||
}
|
||||
result.AddRequiredLineBreakCount(GetRequiredInnerTextLineBreakCount(f));
|
||||
}
|
||||
nsIContent* next = currentNode->GetNextSibling();
|
||||
if (next) {
|
||||
currentNode = next;
|
||||
currentState = AT_NODE;
|
||||
} else {
|
||||
currentNode = currentNode->GetParent();
|
||||
break;
|
||||
}
|
||||
result.AddRequiredLineBreakCount(GetRequiredInnerTextLineBreakCount(f));
|
||||
}
|
||||
nsIContent* next = currentNode->GetNextSibling();
|
||||
if (next) {
|
||||
currentNode = next;
|
||||
currentState = AT_NODE;
|
||||
} else {
|
||||
currentNode = currentNode->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8948,31 +8948,37 @@ nsTextFrame::RecomputeOverflow(nsIFrame* aBlockFrame)
|
|||
return result;
|
||||
}
|
||||
|
||||
static char16_t TransformChar(nsTextFrame* aFrame, const nsStyleText* aStyle,
|
||||
gfxTextRun* aTextRun, uint32_t aSkippedOffset,
|
||||
char16_t aChar)
|
||||
static void TransformChars(nsTextFrame* aFrame, const nsStyleText* aStyle,
|
||||
gfxTextRun* aTextRun, uint32_t aSkippedOffset,
|
||||
const nsTextFragment* aFrag, int32_t aFragOffset,
|
||||
int32_t aFragLen, nsAString& aOut)
|
||||
{
|
||||
if (aChar == '\n') {
|
||||
return aStyle->NewlineIsSignificant(aFrame) ? aChar : ' ';
|
||||
}
|
||||
if (aChar == '\t') {
|
||||
return aStyle->TabIsSignificant() ? aChar : ' ';
|
||||
aOut.SetLength(aOut.Length() + aFragLen);
|
||||
char16_t* out = aOut.EndWriting() - aFragLen;
|
||||
for (int32_t i = 0; i < aFragLen; ++i) {
|
||||
char16_t ch = aFrag->CharAt(aFragOffset + i);
|
||||
if ((ch == '\n' && !aStyle->NewlineIsSignificant(aFrame)) ||
|
||||
(ch == '\t' && !aStyle->TabIsSignificant())) {
|
||||
ch = ' ';
|
||||
}
|
||||
out[i] = ch;
|
||||
}
|
||||
|
||||
switch (aStyle->mTextTransform) {
|
||||
case NS_STYLE_TEXT_TRANSFORM_LOWERCASE:
|
||||
aChar = ToLowerCase(aChar);
|
||||
ToLowerCase(out, out, aFragLen);
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_UPPERCASE:
|
||||
aChar = ToUpperCase(aChar);
|
||||
ToUpperCase(out, out, aFragLen);
|
||||
break;
|
||||
case NS_STYLE_TEXT_TRANSFORM_CAPITALIZE:
|
||||
if (aTextRun->CanBreakLineBefore(aSkippedOffset)) {
|
||||
aChar = ToTitleCase(aChar);
|
||||
for (int32_t i = 0; i < aFragLen; ++i) {
|
||||
if (aTextRun->CanBreakLineBefore(aSkippedOffset + i)) {
|
||||
out[i] = ToTitleCase(out[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return aChar;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -9093,18 +9099,24 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset,
|
|||
const nsStyleText* textStyle = textFrame->StyleText();
|
||||
iter.SetOriginalOffset(trimmedOffsets.mStart);
|
||||
while (iter.GetOriginalOffset() < trimmedOffsets.GetEnd()) {
|
||||
char16_t ch = textFrag->CharAt(iter.GetOriginalOffset());
|
||||
if (iter.IsOriginalCharSkipped()) {
|
||||
if (ch == CH_SHY) {
|
||||
// We should preserve soft hyphens. They can't be transformed.
|
||||
result.mString.Append(ch);
|
||||
int32_t runLength;
|
||||
bool isSkipped = iter.IsOriginalCharSkipped(&runLength);
|
||||
runLength = std::min(runLength,
|
||||
trimmedOffsets.GetEnd() - iter.GetOriginalOffset());
|
||||
if (isSkipped) {
|
||||
for (int32_t i = 0; i < runLength; ++i) {
|
||||
char16_t ch = textFrag->CharAt(iter.GetOriginalOffset() + i);
|
||||
if (ch == CH_SHY) {
|
||||
// We should preserve soft hyphens. They can't be transformed.
|
||||
result.mString.Append(ch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.mString.Append(
|
||||
TransformChar(textFrame, textStyle, textFrame->mTextRun,
|
||||
iter.GetSkippedOffset(), ch));
|
||||
TransformChars(textFrame, textStyle, textFrame->mTextRun,
|
||||
iter.GetSkippedOffset(), textFrag,
|
||||
iter.GetOriginalOffset(), runLength, result.mString);
|
||||
}
|
||||
iter.AdvanceOriginal(1);
|
||||
iter.AdvanceOriginal(runLength);
|
||||
}
|
||||
|
||||
if (trimmedSignificantNewline && GetContentEnd() <= endOffset) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче