зеркало из https://github.com/mozilla/gecko-dev.git
Only keep the old textrun when the frame continuations from the assignment point forward are all empty. b=604843 r=roc a=blocking2.0:final
This commit is contained in:
Родитель
f1046b5715
Коммит
421daa244f
|
@ -1996,68 +1996,6 @@ BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun)
|
|
||||||
{
|
|
||||||
PRUint32 i;
|
|
||||||
for (i = 0; i < mMappedFlows.Length(); ++i) {
|
|
||||||
MappedFlow* mappedFlow = &mMappedFlows[i];
|
|
||||||
nsTextFrame* startFrame = mappedFlow->mStartFrame;
|
|
||||||
nsTextFrame* endFrame = mappedFlow->mEndFrame;
|
|
||||||
nsTextFrame* f;
|
|
||||||
for (f = startFrame; f != endFrame;
|
|
||||||
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
|
|
||||||
#ifdef DEBUG_roc
|
|
||||||
if (f->GetTextRun()) {
|
|
||||||
gfxTextRun* textRun = f->GetTextRun();
|
|
||||||
if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
|
|
||||||
if (mMappedFlows[0].mStartFrame != static_cast<nsTextFrame*>(textRun->GetUserData())) {
|
|
||||||
NS_WARNING("REASSIGNING SIMPLE FLOW TEXT RUN!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
TextRunUserData* userData =
|
|
||||||
static_cast<TextRunUserData*>(textRun->GetUserData());
|
|
||||||
|
|
||||||
if (PRUint32(userData->mMappedFlowCount) >= mMappedFlows.Length() ||
|
|
||||||
userData->mMappedFlows[userData->mMappedFlowCount - 1].mStartFrame !=
|
|
||||||
mMappedFlows[userData->mMappedFlowCount - 1].mStartFrame) {
|
|
||||||
NS_WARNING("REASSIGNING MULTIFLOW TEXT RUN (not append)!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef DEBUG
|
|
||||||
gfxTextRun* oldTextRun = f->GetTextRun();
|
|
||||||
nsTextFrame* firstFrame = nsnull;
|
|
||||||
if (oldTextRun) {
|
|
||||||
if (oldTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
|
|
||||||
firstFrame = static_cast<nsTextFrame*>(oldTextRun->GetUserData());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TextRunUserData* userData =
|
|
||||||
static_cast<TextRunUserData*>(oldTextRun->GetUserData());
|
|
||||||
firstFrame = userData->mMappedFlows[0].mStartFrame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f->ClearTextRun(f);
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (firstFrame && !firstFrame->GetTextRun()) {
|
|
||||||
// oldTextRun was destroyed - assert that we don't reference it.
|
|
||||||
for (PRUint32 i = 0; i < mBreakSinks.Length(); ++i) {
|
|
||||||
NS_ASSERTION(oldTextRun != mBreakSinks[i]->mTextRun,
|
|
||||||
"destroyed text run is still in use");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
f->SetTextRun(aTextRun);
|
|
||||||
}
|
|
||||||
// Set this bit now; we can't set it any earlier because
|
|
||||||
// f->ClearTextRun() might clear it out.
|
|
||||||
startFrame->AddStateBits(TEXT_IN_TEXTRUN_USER_DATA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the flow corresponding to aContent in aUserData
|
// Find the flow corresponding to aContent in aUserData
|
||||||
static inline TextRunMappedFlow*
|
static inline TextRunMappedFlow*
|
||||||
FindFlowForContent(TextRunUserData* aUserData, nsIContent* aContent)
|
FindFlowForContent(TextRunUserData* aUserData, nsIContent* aContent)
|
||||||
|
@ -2102,6 +2040,88 @@ FindFlowForContent(TextRunUserData* aUserData, nsIContent* aContent)
|
||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun)
|
||||||
|
{
|
||||||
|
PRUint32 i;
|
||||||
|
for (i = 0; i < mMappedFlows.Length(); ++i) {
|
||||||
|
MappedFlow* mappedFlow = &mMappedFlows[i];
|
||||||
|
nsTextFrame* startFrame = mappedFlow->mStartFrame;
|
||||||
|
nsTextFrame* endFrame = mappedFlow->mEndFrame;
|
||||||
|
nsTextFrame* f;
|
||||||
|
for (f = startFrame; f != endFrame;
|
||||||
|
f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
|
||||||
|
#ifdef DEBUG_roc
|
||||||
|
if (f->GetTextRun()) {
|
||||||
|
gfxTextRun* textRun = f->GetTextRun();
|
||||||
|
if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
|
||||||
|
if (mMappedFlows[0].mStartFrame != static_cast<nsTextFrame*>(textRun->GetUserData())) {
|
||||||
|
NS_WARNING("REASSIGNING SIMPLE FLOW TEXT RUN!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TextRunUserData* userData =
|
||||||
|
static_cast<TextRunUserData*>(textRun->GetUserData());
|
||||||
|
|
||||||
|
if (PRUint32(userData->mMappedFlowCount) >= mMappedFlows.Length() ||
|
||||||
|
userData->mMappedFlows[userData->mMappedFlowCount - 1].mStartFrame !=
|
||||||
|
mMappedFlows[userData->mMappedFlowCount - 1].mStartFrame) {
|
||||||
|
NS_WARNING("REASSIGNING MULTIFLOW TEXT RUN (not append)!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gfxTextRun* oldTextRun = f->GetTextRun();
|
||||||
|
if (oldTextRun) {
|
||||||
|
nsTextFrame* firstFrame = nsnull;
|
||||||
|
PRUint32 startOffset = 0;
|
||||||
|
if (oldTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
|
||||||
|
firstFrame = static_cast<nsTextFrame*>(oldTextRun->GetUserData());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TextRunUserData* userData = static_cast<TextRunUserData*>(oldTextRun->GetUserData());
|
||||||
|
firstFrame = userData->mMappedFlows[0].mStartFrame;
|
||||||
|
if (NS_UNLIKELY(f != firstFrame)) {
|
||||||
|
TextRunMappedFlow* flow = FindFlowForContent(userData, f->GetContent());
|
||||||
|
if (flow) {
|
||||||
|
startOffset = flow->mDOMOffsetToBeforeTransformOffset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
NS_ERROR("Can't find flow containing frame 'f'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization: if |f| is the first frame in the flow then there are no
|
||||||
|
// prev-continuations that use |oldTextRun|.
|
||||||
|
nsTextFrame* clearFrom = nsnull;
|
||||||
|
if (NS_UNLIKELY(f != firstFrame)) {
|
||||||
|
// If all the frames in the mapped flow starting at |f| (inclusive)
|
||||||
|
// are empty then we let the prev-continuations keep the old text run.
|
||||||
|
gfxSkipCharsIterator iter(oldTextRun->GetSkipChars(), startOffset, f->GetContentOffset());
|
||||||
|
PRUint32 textRunOffset = iter.ConvertOriginalToSkipped(f->GetContentOffset());
|
||||||
|
clearFrom = textRunOffset == oldTextRun->GetLength() ? f : nsnull;
|
||||||
|
}
|
||||||
|
f->ClearTextRun(clearFrom);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (firstFrame && !firstFrame->GetTextRun()) {
|
||||||
|
// oldTextRun was destroyed - assert that we don't reference it.
|
||||||
|
for (PRUint32 i = 0; i < mBreakSinks.Length(); ++i) {
|
||||||
|
NS_ASSERTION(oldTextRun != mBreakSinks[i]->mTextRun,
|
||||||
|
"destroyed text run is still in use");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
f->SetTextRun(aTextRun);
|
||||||
|
}
|
||||||
|
// Set this bit now; we can't set it any earlier because
|
||||||
|
// f->ClearTextRun() might clear it out.
|
||||||
|
startFrame->AddStateBits(TEXT_IN_TEXTRUN_USER_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gfxSkipCharsIterator
|
gfxSkipCharsIterator
|
||||||
nsTextFrame::EnsureTextRun(gfxContext* aReferenceContext, nsIFrame* aLineContainer,
|
nsTextFrame::EnsureTextRun(gfxContext* aReferenceContext, nsIFrame* aLineContainer,
|
||||||
const nsLineList::iterator* aLine,
|
const nsLineList::iterator* aLine,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче