Support revised first-letter layout
This commit is contained in:
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,6 @@
|
|||||||
|
|
||||||
// XXX temporary for :first-letter support
|
// XXX temporary for :first-letter support
|
||||||
#include "nsITextContent.h"
|
#include "nsITextContent.h"
|
||||||
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|
||||||
|
|
||||||
// XXX for IsEmptyLine
|
// XXX for IsEmptyLine
|
||||||
#include "nsTextFragment.h"
|
#include "nsTextFragment.h"
|
||||||
@@ -87,6 +86,10 @@ static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);/* XXX */
|
|||||||
|
|
||||||
// Debugging support code
|
// Debugging support code
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static PRBool gShowDirtyLines = PR_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_INCREMENTAL_REFLOW
|
#ifdef NOISY_INCREMENTAL_REFLOW
|
||||||
static PRInt32 gNoiseIndent;
|
static PRInt32 gNoiseIndent;
|
||||||
static const char* kReflowCommandType[] = {
|
static const char* kReflowCommandType[] = {
|
||||||
@@ -926,6 +929,9 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (nsnull != view) {
|
if (nsnull != view) {
|
||||||
fprintf(out, " [view=%p]", view);
|
fprintf(out, " [view=%p]", view);
|
||||||
}
|
}
|
||||||
|
if (nsnull != mNextSibling) {
|
||||||
|
fprintf(out, " next=%p", mNextSibling);
|
||||||
|
}
|
||||||
|
|
||||||
// Output the flow linkage
|
// Output the flow linkage
|
||||||
if (nsnull != mPrevInFlow) {
|
if (nsnull != mPrevInFlow) {
|
||||||
@@ -943,7 +949,7 @@ nsBlockFrame::List(FILE* out, PRInt32 aIndent) const
|
|||||||
if (0 != mFlags) {
|
if (0 != mFlags) {
|
||||||
fprintf(out, " [flags=%x]", mFlags);
|
fprintf(out, " [flags=%x]", mFlags);
|
||||||
}
|
}
|
||||||
fputs("<\n", out);
|
fprintf(out, " sc=%p<\n", mStyleContext);
|
||||||
aIndent++;
|
aIndent++;
|
||||||
|
|
||||||
// Output the lines
|
// Output the lines
|
||||||
@@ -1128,6 +1134,7 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
case nsIReflowCommand::FrameAppended:
|
case nsIReflowCommand::FrameAppended:
|
||||||
case nsIReflowCommand::FrameInserted:
|
case nsIReflowCommand::FrameInserted:
|
||||||
case nsIReflowCommand::FrameRemoved:
|
case nsIReflowCommand::FrameRemoved:
|
||||||
|
NS_NOTREACHED("invalid reflow command");
|
||||||
break;
|
break;
|
||||||
case nsIReflowCommand::StyleChanged:
|
case nsIReflowCommand::StyleChanged:
|
||||||
rv = PrepareStyleChangedReflow(state);
|
rv = PrepareStyleChangedReflow(state);
|
||||||
@@ -1189,6 +1196,16 @@ nsBlockFrame::Reflow(nsIPresContext& aPresContext,
|
|||||||
// Compute our final size
|
// Compute our final size
|
||||||
ComputeFinalSize(aReflowState, state, aMetrics);
|
ComputeFinalSize(aReflowState, state, aMetrics);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines && (eReflowReason_Resize == aReflowState.reason)) {
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->ClearWasDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
printf(": availSize=%d,%d computed=%d,%d metrics=%d,%d carriedMargin=%d\n",
|
||||||
@@ -1588,8 +1605,14 @@ nsresult
|
|||||||
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
nsBlockFrame::PrepareStyleChangedReflow(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
UpdateBulletPosition();
|
UpdateBulletPosition();
|
||||||
// XXX temporary
|
|
||||||
return PrepareResizeReflow(aState);
|
// Mark everything dirty
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
while (nsnull != line) {
|
||||||
|
line->MarkDirty();
|
||||||
|
line = line->mNext;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
@@ -1908,6 +1931,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
|||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
aLine->MarkWasDirty();
|
||||||
|
#endif
|
||||||
|
|
||||||
// If the line is empty then first pull a frame into it so that we
|
// If the line is empty then first pull a frame into it so that we
|
||||||
// know what kind of line it is (block or inline).
|
// know what kind of line it is (block or inline).
|
||||||
if (0 == aLine->ChildCount()) {
|
if (0 == aLine->ChildCount()) {
|
||||||
@@ -2655,6 +2682,10 @@ nsBlockFrame::ReflowInlineFrames(nsBlockReflowState& aState,
|
|||||||
availWidth, availHeight,
|
availWidth, availHeight,
|
||||||
impactedByFloaters,
|
impactedByFloaters,
|
||||||
PR_FALSE /*XXX isTopOfPage*/);
|
PR_FALSE /*XXX isTopOfPage*/);
|
||||||
|
if ((0 == lineLayout->GetLineNumber()) &&
|
||||||
|
(NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
|
||||||
|
lineLayout->SetFirstLetterStyleOK(PR_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
// Reflow the frames that are already on the line first
|
// Reflow the frames that are already on the line first
|
||||||
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
PRUint8 lineReflowStatus = LINE_REFLOW_OK;
|
||||||
@@ -2773,6 +2804,12 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
// If it's currently ok to be reflowing in first-letter style then
|
// If it's currently ok to be reflowing in first-letter style then
|
||||||
// we must be about to reflow a frame that has first-letter style.
|
// we must be about to reflow a frame that has first-letter style.
|
||||||
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
PRBool reflowingFirstLetter = aState.mLineLayout->GetFirstLetterStyleOK();
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": reflowing ");
|
||||||
|
nsFrame::ListTag(stdout, aFrame);
|
||||||
|
printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Reflow the inline frame
|
// Reflow the inline frame
|
||||||
nsLineLayout* lineLayout = aState.mLineLayout;
|
nsLineLayout* lineLayout = aState.mLineLayout;
|
||||||
@@ -2868,14 +2905,25 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool needSplit = PR_FALSE;
|
// If we are reflowing the first letter frame then don't split the
|
||||||
if (!reflowingFirstLetter) {
|
// line and don't stop the line reflow...
|
||||||
needSplit = PR_TRUE;
|
PRBool splitLine = !reflowingFirstLetter;
|
||||||
|
if (reflowingFirstLetter) {
|
||||||
|
if (aLine->IsFirstLine()) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
nsIAtom* frameType;
|
||||||
|
if (NS_SUCCEEDED(aFrame->GetFrameType(&frameType)) && frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
splitLine = PR_TRUE;
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needSplit) {
|
if (splitLine) {
|
||||||
// Split line after the current frame
|
// Split line after the current frame
|
||||||
*aLineReflowStatus = LINE_REFLOW_STOP;
|
*aLineReflowStatus = LINE_REFLOW_STOP;
|
||||||
aFrame->GetNextSibling(&aFrame);
|
aFrame->GetNextSibling(&aFrame);
|
||||||
@@ -2883,6 +2931,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
|
|||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark next line dirty in case SplitLine didn't end up
|
// Mark next line dirty in case SplitLine didn't end up
|
||||||
// pushing any frames.
|
// pushing any frames.
|
||||||
nsLineBox* next = aLine->mNext;
|
nsLineBox* next = aLine->mNext;
|
||||||
@@ -3400,6 +3449,59 @@ nsBlockFrame::LastChild()
|
|||||||
return nsnull;
|
return nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
nsresult
|
||||||
|
nsBlockFrame::WrapFrameInFirstLetterFrame(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsLineBox* line = mLines;
|
||||||
|
if (!line || line->IsBlock()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
NS_ASSERTION(line->mChildCount > 0, "bad line count");
|
||||||
|
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
if (line->IsFirstLine()) {
|
||||||
|
// Delegate wrapping to the line frame
|
||||||
|
}
|
||||||
|
else if (line->mFirstChild) {
|
||||||
|
// Examine first frame on the line. If its text, then
|
||||||
|
nsIFrame* frame = line->mFirstChild;
|
||||||
|
nsIAtom* frameType;
|
||||||
|
frame->GetFrameType(&frameType);
|
||||||
|
if (frameType) {
|
||||||
|
if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
|
// Time to rap. badda boom. :-)
|
||||||
|
nsIFrame* newFrame;
|
||||||
|
rv = NS_NewFirstLetterFrame(&newFrame);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
// Give text frame to the new frame and then splice in the
|
||||||
|
// first-letter frame in its place.
|
||||||
|
nsIFrame* nextSib;
|
||||||
|
frame->GetNextSibling(&nextSib);
|
||||||
|
frame->SetNextSibling(nsnull);
|
||||||
|
line->mFirstChild = newFrame;
|
||||||
|
line->MarkDirty();
|
||||||
|
|
||||||
|
// Initialize the first-letter-frame.
|
||||||
|
rv = newFrame->Init(*aPresContext, mContent, this,
|
||||||
|
GetFirstLetterStyle(aPresContext), nsnull);
|
||||||
|
newFrame->SetInitialChildList(*aPresContext, nsnull, frame);
|
||||||
|
|
||||||
|
// See if the first-letter-frame should be floating, and if
|
||||||
|
// it is then create a placeholder for it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (frameType == nsLayoutAtoms::inlineFrame) {
|
||||||
|
// Delegate wrapping to the inline frame
|
||||||
|
}
|
||||||
|
NS_RELEASE(frameType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
nsBlockFrame::WrapFramesInFirstLineFrame(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -3738,6 +3840,13 @@ nsBlockFrame::AddFrames(nsIPresContext* aPresContext,
|
|||||||
// We just added one or more frame(s) to the first line.
|
// We just added one or more frame(s) to the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4124,6 +4233,13 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
|||||||
// removed a block that preceeded the first line.
|
// removed a block that preceeded the first line.
|
||||||
WrapFramesInFirstLineFrame(aPresContext);
|
WrapFramesInFirstLineFrame(aPresContext);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if ((NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState) &&
|
||||||
|
(nsnull != mLines) && !mLines->IsBlock()) {
|
||||||
|
// We just added one or more frame(s) to the first line.
|
||||||
|
WrapFrameInFirstLetterFrame(aPresContext);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
VerifyLines(PR_TRUE);
|
VerifyLines(PR_TRUE);
|
||||||
@@ -4913,6 +5029,14 @@ nsBlockFrame::PaintChildren(nsIPresContext& aPresContext,
|
|||||||
aWhichLayer);
|
aWhichLayer);
|
||||||
kid->GetNextSibling(&kid);
|
kid->GetNextSibling(&kid);
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (gShowDirtyLines) {
|
||||||
|
if (line->WasDirty()) {
|
||||||
|
aRenderingContext.SetColor(NS_RGB(128, 255, 128));
|
||||||
|
aRenderingContext.DrawRect(line->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef NOISY_DAMAGE_REPAIR
|
#ifdef NOISY_DAMAGE_REPAIR
|
||||||
else {
|
else {
|
||||||
@@ -5054,6 +5178,16 @@ nsBlockFrame::Init(nsIPresContext& aPresContext,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStyleContext*
|
||||||
|
nsBlockFrame::GetFirstLetterStyle(nsIPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
nsIStyleContext* fls;
|
||||||
|
aPresContext->ProbePseudoStyleContextFor(mContent,
|
||||||
|
nsHTMLAtoms::firstLetterPseudo,
|
||||||
|
mStyleContext, PR_FALSE, &fls);
|
||||||
|
return fls;
|
||||||
|
}
|
||||||
|
|
||||||
nsIStyleContext*
|
nsIStyleContext*
|
||||||
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
nsBlockFrame::GetFirstLineStyle(nsIPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
@@ -5077,20 +5211,29 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
// Lookup up the two pseudo style contexts
|
// Lookup up the two pseudo style contexts
|
||||||
nsIStyleContext* firstLineStyle = nsnull;
|
|
||||||
if (nsnull == mPrevInFlow) {
|
if (nsnull == mPrevInFlow) {
|
||||||
firstLineStyle = GetFirstLineStyle(&aPresContext);
|
nsIStyleContext* firstLetterStyle = GetFirstLetterStyle(&aPresContext);
|
||||||
|
if (nsnull != firstLetterStyle) {
|
||||||
|
mState |= NS_BLOCK_HAS_FIRST_LETTER_STYLE;
|
||||||
|
#ifdef NOISY_FIRST_LETTER
|
||||||
|
ListTag(stdout);
|
||||||
|
printf(": first-letter style found\n");
|
||||||
|
#endif
|
||||||
|
NS_RELEASE(firstLetterStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIStyleContext* firstLineStyle = GetFirstLineStyle(&aPresContext);
|
||||||
if (nsnull != firstLineStyle) {
|
if (nsnull != firstLineStyle) {
|
||||||
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
mState |= NS_BLOCK_HAS_FIRST_LINE_STYLE;
|
||||||
#ifdef NOISY_FIRST_LINE
|
#ifdef NOISY_FIRST_LINE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": first-line style found\n");
|
printf(": first-line style found\n");
|
||||||
#endif
|
#endif
|
||||||
|
NS_RELEASE(firstLineStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
rv = AddFrames(&aPresContext, aChildList, nsnull);
|
||||||
NS_IF_RELEASE(firstLineStyle);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user