--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -460,17 +460,17 @@ TextOverflow::AnalyzeMarkerEdges(nsIFram
}
} else {
// frame is inside
aAlignmentEdges->Accumulate(mBlockWM, borderRect);
*aFoundVisibleTextOrAtomic = true;
}
}
-void
+LogicalRect
TextOverflow::ExamineLineFrames(nsLineBox* aLine,
FrameHashtable* aFramesToHide,
AlignmentEdges* aAlignmentEdges)
{
// No ellipsing for 'clip' style.
bool suppressIStart = mIStart.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP;
bool suppressIEnd = mIEnd.mStyle->mType == NS_STYLE_TEXT_OVERFLOW_CLIP;
if (mCanHaveInlineAxisScrollbar) {
@@ -484,29 +484,39 @@ TextOverflow::ExamineLineFrames(nsLineBo
suppressIStart = true;
}
if (pos.I(mBlockWM) >= scrollRange.IEnd(mBlockWM)) {
suppressIEnd = true;
}
}
LogicalRect contentArea = mContentArea;
- const nscoord scrollAdjust = mAdjustForPixelSnapping ?
- mBlock->PresContext()->AppUnitsPerDevPixel() : 0;
- InflateIStart(mBlockWM, &contentArea, scrollAdjust);
- InflateIEnd(mBlockWM, &contentArea, scrollAdjust);
+ bool snapStart = true, snapEnd = true;
+ // Save the non-snapped area since that's what we want to use when placing
+ // the markers (our return value). The snapped area is only for analysis.
+ LogicalRect nonSnappedContentArea = contentArea;
+ if (mAdjustForPixelSnapping) {
+ const nscoord scrollAdjust = mBlock->PresContext()->AppUnitsPerDevPixel();
+ if (snapStart) {
+ InflateIStart(mBlockWM, &contentArea, scrollAdjust);
+ }
+ if (snapEnd) {
+ InflateIEnd(mBlockWM, &contentArea, scrollAdjust);
+ }
+ }
+
LogicalRect lineRect(mBlockWM, aLine->GetScrollableOverflowArea(),
mBlockSize);
const bool istartOverflow =
!suppressIStart && lineRect.IStart(mBlockWM) < contentArea.IStart(mBlockWM);
const bool iendOverflow =
!suppressIEnd && lineRect.IEnd(mBlockWM) > contentArea.IEnd(mBlockWM);
if (!istartOverflow && !iendOverflow) {
// The line does not overflow on a side we should ellipsize.
- return;
+ return nonSnappedContentArea;
}
int pass = 0;
bool retryEmptyLine = true;
bool guessIStart = istartOverflow;
bool guessIEnd = iendOverflow;
mIStart.mActive = istartOverflow;
mIEnd.mActive = iendOverflow;
@@ -527,17 +537,17 @@ TextOverflow::ExamineLineFrames(nsLineBo
nscoord iendMarkerISize = mIEnd.mActive ? mIEnd.mISize : 0;
if (istartMarkerISize && iendMarkerISize &&
istartMarkerISize + iendMarkerISize > contentArea.ISize(mBlockWM)) {
istartMarkerISize = 0;
}
// Calculate the area between the potential markers aligned at the
// block's edge.
- LogicalRect insideMarkersArea = mContentArea;
+ LogicalRect insideMarkersArea = nonSnappedContentArea;
if (guessIStart) {
InflateIStart(mBlockWM, &insideMarkersArea, -istartMarkerISize);
}
if (guessIEnd) {
InflateIEnd(mBlockWM, &insideMarkersArea, -iendMarkerISize);
}
// Analyze the frames on aLine for the overflow situation at the content
@@ -553,31 +563,32 @@ TextOverflow::ExamineLineFrames(nsLineBo
&clippedMarkerEdges);
}
if (!foundVisibleTextOrAtomic && retryEmptyLine) {
aAlignmentEdges->mAssigned = false;
aFramesToHide->Clear();
pass = -1;
if (mIStart.IsNeeded() && mIStart.mActive && !clippedIStartMarker) {
if (clippedMarkerEdges.mAssignedIStart &&
- clippedMarkerEdges.mIStart > mContentArea.IStart(mBlockWM)) {
- mIStart.mISize =
- clippedMarkerEdges.mIStart - mContentArea.IStart(mBlockWM);
+ clippedMarkerEdges.mIStart > nonSnappedContentArea.IStart(mBlockWM)) {
+ mIStart.mISize = clippedMarkerEdges.mIStart -
+ nonSnappedContentArea.IStart(mBlockWM);
NS_ASSERTION(mIStart.mISize < mIStart.mIntrinsicISize,
"clipping a marker should make it strictly smaller");
clippedIStartMarker = true;
} else {
mIStart.mActive = guessIStart = false;
}
continue;
}
if (mIEnd.IsNeeded() && mIEnd.mActive && !clippedIEndMarker) {
if (clippedMarkerEdges.mAssignedIEnd &&
- mContentArea.IEnd(mBlockWM) > clippedMarkerEdges.mIEnd) {
- mIEnd.mISize = mContentArea.IEnd(mBlockWM) - clippedMarkerEdges.mIEnd;
+ nonSnappedContentArea.IEnd(mBlockWM) > clippedMarkerEdges.mIEnd) {
+ mIEnd.mISize = nonSnappedContentArea.IEnd(mBlockWM) -
+ clippedMarkerEdges.mIEnd;
NS_ASSERTION(mIEnd.mISize < mIEnd.mIntrinsicISize,
"clipping a marker should make it strictly smaller");
clippedIEndMarker = true;
} else {
mIEnd.mActive = guessIEnd = false;
}
continue;
}
@@ -603,50 +614,52 @@ TextOverflow::ExamineLineFrames(nsLineBo
NS_ASSERTION(pass == 0, "2nd pass should never guess wrong");
} while (++pass != 2);
if (!istartOverflow || !mIStart.mActive) {
mIStart.Reset();
}
if (!iendOverflow || !mIEnd.mActive) {
mIEnd.Reset();
}
+ return nonSnappedContentArea;
}
void
TextOverflow::ProcessLine(const nsDisplayListSet& aLists,
nsLineBox* aLine)
{
NS_ASSERTION(mIStart.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
mIEnd.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP,
"TextOverflow with 'clip' for both sides");
mIStart.Reset();
mIStart.mActive = mIStart.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP;
mIEnd.Reset();
mIEnd.mActive = mIEnd.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP;
FrameHashtable framesToHide(64);
AlignmentEdges alignmentEdges;
- ExamineLineFrames(aLine, &framesToHide, &alignmentEdges);
+ const LogicalRect contentArea =
+ ExamineLineFrames(aLine, &framesToHide, &alignmentEdges);
bool needIStart = mIStart.IsNeeded();
bool needIEnd = mIEnd.IsNeeded();
if (!needIStart && !needIEnd) {
return;
}
NS_ASSERTION(mIStart.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
!needIStart, "left marker for 'clip'");
NS_ASSERTION(mIEnd.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
!needIEnd, "right marker for 'clip'");
// If there is insufficient space for both markers then keep the one on the
// end side per the block's 'direction'.
if (needIStart && needIEnd &&
- mIStart.mISize + mIEnd.mISize > mContentArea.ISize(mBlockWM)) {
+ mIStart.mISize + mIEnd.mISize > contentArea.ISize(mBlockWM)) {
needIStart = false;
}
- LogicalRect insideMarkersArea = mContentArea;
+ LogicalRect insideMarkersArea = contentArea;
if (needIStart) {
InflateIStart(mBlockWM, &insideMarkersArea, -mIStart.mISize);
}
if (needIEnd) {
InflateIEnd(mBlockWM, &insideMarkersArea, -mIEnd.mISize);
}
if (!mCanHaveInlineAxisScrollbar && alignmentEdges.mAssigned) {
LogicalRect alignmentRect(mBlockWM, alignmentEdges.mIStart,
@@ -655,17 +668,17 @@ TextOverflow::ProcessLine(const nsDispla
insideMarkersArea.IntersectRect(insideMarkersArea, alignmentRect);
}
// Clip and remove display items as needed at the final marker edges.
nsDisplayList* lists[] = { aLists.Content(), aLists.PositionedDescendants() };
for (uint32_t i = 0; i < ArrayLength(lists); ++i) {
PruneDisplayListContents(lists[i], framesToHide, insideMarkersArea);
}
- CreateMarkers(aLine, needIStart, needIEnd, insideMarkersArea);
+ CreateMarkers(aLine, needIStart, needIEnd, insideMarkersArea, contentArea);
}
void
TextOverflow::PruneDisplayListContents(nsDisplayList* aList,
const FrameHashtable& aFramesToHide,
const LogicalRect& aInsideMarkersArea)
{
nsDisplayList saved;
@@ -749,45 +762,46 @@ TextOverflow::CanHaveTextOverflow(nsIFra
}
}
return true;
}
void
TextOverflow::CreateMarkers(const nsLineBox* aLine,
bool aCreateIStart, bool aCreateIEnd,
- const mozilla::LogicalRect& aInsideMarkersArea)
+ const LogicalRect& aInsideMarkersArea,
+ const LogicalRect& aContentArea)
{
if (aCreateIStart) {
DisplayListClipState::AutoSaveRestore clipState(mBuilder);
LogicalRect markerLogicalRect(
mBlockWM, aInsideMarkersArea.IStart(mBlockWM) - mIStart.mIntrinsicISize,
aLine->BStart(), mIStart.mIntrinsicISize, aLine->BSize());
nsPoint offset = mBuilder->ToReferenceFrame(mBlock);
nsRect markerRect =
markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockSize) + offset;
- ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
+ ClipMarker(aContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
markerRect, clipState);
nsDisplayItem* marker = new (mBuilder)
nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
aLine->GetLogicalAscent(), mIStart.mStyle, 0);
mMarkerList.AppendNewToTop(marker);
}
if (aCreateIEnd) {
DisplayListClipState::AutoSaveRestore clipState(mBuilder);
LogicalRect markerLogicalRect(
mBlockWM, aInsideMarkersArea.IEnd(mBlockWM), aLine->BStart(),
mIEnd.mIntrinsicISize, aLine->BSize());
nsPoint offset = mBuilder->ToReferenceFrame(mBlock);
nsRect markerRect =
markerLogicalRect.GetPhysicalRect(mBlockWM, mBlockSize) + offset;
- ClipMarker(mContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
+ ClipMarker(aContentArea.GetPhysicalRect(mBlockWM, mBlockSize) + offset,
markerRect, clipState);
nsDisplayItem* marker = new (mBuilder)
nsDisplayTextOverflowMarker(mBuilder, mBlock, markerRect,
aLine->GetLogicalAscent(), mIEnd.mStyle, 1);
mMarkerList.AppendNewToTop(marker);
}
}
--- a/layout/generic/TextOverflow.h
+++ b/layout/generic/TextOverflow.h
@@ -121,20 +121,22 @@ class TextOverflow {
/**
* Examines frames on the line to determine whether we should draw a left
* and/or right marker, and if so, which frames should be completely hidden
* and the bounds of what will be displayed between the markers.
* @param aLine the line we're processing
* @param aFramesToHide frames that should have their display items removed
* @param aAlignmentEdges the outermost edges of all text and atomic
* inline-level frames that are inside the area between the markers
+ * @return the area inside which we should add any markers;
+ * this is the block's content area.
*/
- void ExamineLineFrames(nsLineBox* aLine,
- FrameHashtable* aFramesToHide,
- AlignmentEdges* aAlignmentEdges);
+ LogicalRect ExamineLineFrames(nsLineBox* aLine,
+ FrameHashtable* aFramesToHide,
+ AlignmentEdges* aAlignmentEdges);
/**
* LineHasOverflowingText calls this to analyze edges, both the block's
* content edges and the hypothetical marker edges aligned at the block edges.
* @param aFrame the descendant frame of mBlock that we're analyzing
* @param aContentArea the block's content area
* @param aInsideMarkersArea the rectangle between the markers
* @param aFramesToHide frames that should have their display items removed
@@ -193,20 +195,23 @@ class TextOverflow {
/**
* ProcessLine calls this to create display items for the markers and insert
* them into mMarkerList.
* @param aLine the line we're processing
* @param aCreateIStart if true, create a marker on the inline start side
* @param aCreateIEnd if true, create a marker on the inline end side
* @param aInsideMarkersArea is the area inside the markers
+ * @param aContentArea is the area inside which we should add the markers;
+ * this is the block's content area.
*/
void CreateMarkers(const nsLineBox* aLine,
bool aCreateIStart, bool aCreateIEnd,
- const LogicalRect& aInsideMarkersArea);
+ const LogicalRect& aInsideMarkersArea,
+ const LogicalRect& aContentArea);
LogicalRect mContentArea;
nsDisplayListBuilder* mBuilder;
nsIFrame* mBlock;
nsIScrollableFrame* mScrollableFrame;
nsDisplayList mMarkerList;
nsSize mBlockSize;
WritingMode mBlockWM;