mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 727125 - Update overflow areas for text frames on text-decoration change to ensure text-decoration on hover is visible. r=dbaron
This commit is contained in:
parent
5161839fdc
commit
4451470f2b
@ -513,6 +513,22 @@ RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint)
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
RestyleManager::AddSubtreeToOverflowTracker(nsIFrame* aFrame)
|
||||
{
|
||||
mOverflowChangedTracker.AddFrame(
|
||||
aFrame,
|
||||
OverflowChangedTracker::CHILDREN_AND_PARENT_CHANGED);
|
||||
nsIFrame::ChildListIterator lists(aFrame);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
nsIFrame* child = childFrames.get();
|
||||
AddSubtreeToOverflowTracker(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(ChangeListProperty, nullptr)
|
||||
|
||||
/**
|
||||
@ -716,6 +732,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
StyleChangeReflow(frame, hint);
|
||||
didReflowThisFrame = true;
|
||||
}
|
||||
|
||||
if (hint & (nsChangeHint_RepaintFrame | nsChangeHint_SyncFrameView |
|
||||
nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateTransformLayer |
|
||||
nsChangeHint_ChildrenOnlyTransform)) {
|
||||
@ -733,7 +750,11 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
"nsChangeHint_UpdateOverflow should be passed too");
|
||||
if (!didReflowThisFrame &&
|
||||
(hint & (nsChangeHint_UpdateOverflow |
|
||||
nsChangeHint_UpdatePostTransformOverflow))) {
|
||||
nsChangeHint_UpdatePostTransformOverflow |
|
||||
nsChangeHint_UpdateSubtreeOverflow))) {
|
||||
if (hint & nsChangeHint_UpdateSubtreeOverflow) {
|
||||
AddSubtreeToOverflowTracker(frame);
|
||||
}
|
||||
OverflowChangedTracker::ChangeKind changeKind;
|
||||
if (hint & nsChangeHint_ChildrenOnlyTransform) {
|
||||
// The overflow areas of the child frames need to be updated:
|
||||
@ -769,7 +790,8 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
|
||||
// If we have both nsChangeHint_UpdateOverflow and
|
||||
// nsChangeHint_UpdatePostTransformOverflow, CHILDREN_AND_PARENT_CHANGED
|
||||
// is selected as it is stronger.
|
||||
if (hint & nsChangeHint_UpdateOverflow) {
|
||||
if (hint & (nsChangeHint_UpdateOverflow |
|
||||
nsChangeHint_UpdateSubtreeOverflow)) {
|
||||
changeKind = OverflowChangedTracker::CHILDREN_AND_PARENT_CHANGED;
|
||||
} else {
|
||||
changeKind = OverflowChangedTracker::TRANSFORM_CHANGED;
|
||||
|
@ -245,6 +245,9 @@ private:
|
||||
|
||||
void StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
|
||||
|
||||
// Recursively add all the given frame and all children to the tracker.
|
||||
void AddSubtreeToOverflowTracker(nsIFrame* aFrame);
|
||||
|
||||
// Returns true if this function managed to successfully move a frame, and
|
||||
// false if it could not process the position change, and a reflow should
|
||||
// be performed instead.
|
||||
|
@ -72,23 +72,28 @@ enum nsChangeHint {
|
||||
nsChangeHint_ReconstructFrame = 0x400,
|
||||
|
||||
/**
|
||||
* The frame's overflow area has changed, either through a change in its
|
||||
* transform or a change in its position. Does not update any descendant
|
||||
* The frame's overflow area has changed. Does not update any descendant
|
||||
* frames.
|
||||
*/
|
||||
nsChangeHint_UpdateOverflow = 0x800,
|
||||
|
||||
/**
|
||||
* The overflow area of the frame and all of its descendants has changed. This
|
||||
* can happen through a text-decoration change.
|
||||
*/
|
||||
nsChangeHint_UpdateSubtreeOverflow = 0x1000,
|
||||
|
||||
/**
|
||||
* The frame's overflow area has changed, through a change in its transform.
|
||||
* Does not update any descendant frames.
|
||||
*/
|
||||
nsChangeHint_UpdatePostTransformOverflow = 0x1000,
|
||||
nsChangeHint_UpdatePostTransformOverflow = 0x2000,
|
||||
|
||||
/**
|
||||
* The children-only transform of an SVG frame changed, requiring the
|
||||
* overflow rects of the frame's immediate children to be updated.
|
||||
*/
|
||||
nsChangeHint_ChildrenOnlyTransform = 0x2000,
|
||||
nsChangeHint_ChildrenOnlyTransform = 0x4000,
|
||||
|
||||
/**
|
||||
* The frame's offsets have changed, while its dimensions might have
|
||||
@ -100,7 +105,7 @@ enum nsChangeHint {
|
||||
* nsChangeHint_UpdateOverflow in order to get the overflow areas of
|
||||
* the ancestors updated as well.
|
||||
*/
|
||||
nsChangeHint_RecomputePosition = 0x4000,
|
||||
nsChangeHint_RecomputePosition = 0x8000,
|
||||
|
||||
/**
|
||||
* Behaves like ReconstructFrame, but only if the frame has descendants
|
||||
@ -108,7 +113,7 @@ enum nsChangeHint {
|
||||
* has changed whether the frame is a container for fixed-pos or abs-pos
|
||||
* elements, but reframing is otherwise not needed.
|
||||
*/
|
||||
nsChangeHint_AddOrRemoveTransform = 0x8000,
|
||||
nsChangeHint_AddOrRemoveTransform = 0x10000,
|
||||
|
||||
/**
|
||||
* This change hint has *no* change handling behavior. However, it
|
||||
@ -116,13 +121,13 @@ enum nsChangeHint {
|
||||
* changes, and it's inherited by a child, that might require a reflow
|
||||
* due to the border-width change on the child.
|
||||
*/
|
||||
nsChangeHint_BorderStyleNoneChange = 0x10000,
|
||||
nsChangeHint_BorderStyleNoneChange = 0x20000,
|
||||
|
||||
/**
|
||||
* SVG textPath needs to be recomputed because the path has changed.
|
||||
* This means that the glyph positions of the text need to be recomputed.
|
||||
*/
|
||||
nsChangeHint_UpdateTextPath = 0x20000
|
||||
nsChangeHint_UpdateTextPath = 0x40000
|
||||
|
||||
// IMPORTANT NOTE: When adding new hints, consider whether you need to
|
||||
// add them to NS_HintsNotHandledForDescendantsIn() below.
|
||||
|
@ -4803,7 +4803,7 @@ GetInflationForTextDecorations(nsIFrame* aFrame, nscoord aInflationMinFontSize)
|
||||
|
||||
void
|
||||
nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aBlockReflowState,
|
||||
nsIFrame* aBlock,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect,
|
||||
bool aIncludeTextDecorations)
|
||||
@ -4816,8 +4816,8 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
if (IsFloatingFirstLetterChild()) {
|
||||
// The underline/overline drawable area must be contained in the overflow
|
||||
// rect when this is in floating first letter frame at *both* modes.
|
||||
nsIFrame* firstLetterFrame = aBlockReflowState.frame;
|
||||
uint8_t decorationStyle = firstLetterFrame->StyleContext()->
|
||||
// In this case, aBlock is the ::first-letter frame.
|
||||
uint8_t decorationStyle = aBlock->StyleContext()->
|
||||
StyleTextReset()->GetDecorationStyle();
|
||||
// If the style is none, let's include decoration line rect as solid style
|
||||
// since changing the style from none to solid/dotted/dashed doesn't cause
|
||||
@ -4861,7 +4861,7 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
GetTextDecorations(aPresContext, eResolvedColors, textDecs);
|
||||
if (textDecs.HasDecorationLines()) {
|
||||
nscoord inflationMinFontSize =
|
||||
nsLayoutUtils::InflationMinFontSizeFor(aBlockReflowState.frame);
|
||||
nsLayoutUtils::InflationMinFontSizeFor(aBlock);
|
||||
|
||||
const nscoord width = GetSize().width;
|
||||
const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(),
|
||||
@ -8046,7 +8046,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth,
|
||||
// When we have text decorations, we don't need to compute their overflow now
|
||||
// because we're guaranteed to do it later
|
||||
// (see nsLineLayout::RelativePositionFrames)
|
||||
UnionAdditionalOverflow(presContext, *aLineLayout.LineContainerRS(),
|
||||
UnionAdditionalOverflow(presContext, aLineLayout.LineContainerRS()->frame,
|
||||
provider, &aMetrics.VisualOverflow(), false);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
@ -8288,7 +8288,7 @@ nsTextFrame::RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState)
|
||||
&provider);
|
||||
nsRect &vis = result.VisualOverflow();
|
||||
vis.UnionRect(vis, RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent));
|
||||
UnionAdditionalOverflow(PresContext(), aBlockReflowState, provider,
|
||||
UnionAdditionalOverflow(PresContext(), aBlockReflowState.frame, provider,
|
||||
&vis, true);
|
||||
return result;
|
||||
}
|
||||
@ -8579,3 +8579,36 @@ nsTextFrame::HasAnyNoncollapsedCharacters()
|
||||
int32_t skippedOffsetEnd = iter.ConvertOriginalToSkipped(offsetEnd);
|
||||
return skippedOffset != skippedOffsetEnd;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTextFrame::UpdateOverflow()
|
||||
{
|
||||
nsRect rect(nsPoint(0, 0), GetSize());
|
||||
nsOverflowAreas overflowAreas(rect, rect);
|
||||
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
return false;
|
||||
}
|
||||
gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated);
|
||||
if (!mTextRun) {
|
||||
return false;
|
||||
}
|
||||
PropertyProvider provider(this, iter, nsTextFrame::eInflated);
|
||||
provider.InitializeForDisplay(true);
|
||||
|
||||
nsIFrame*decorationsBlock;
|
||||
if (IsFloatingFirstLetterChild()) {
|
||||
decorationsBlock = GetParent();
|
||||
} else {
|
||||
for (nsIFrame* f = this; f; f = f->GetParent()) {
|
||||
nsBlockFrame* fBlock = nsLayoutUtils::GetAsBlock(f);
|
||||
if (fBlock) {
|
||||
decorationsBlock = fBlock;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
UnionAdditionalOverflow(PresContext(), decorationsBlock, provider,
|
||||
&overflowAreas.VisualOverflow(), true);
|
||||
return FinishAndStoreOverflow(overflowAreas, GetSize());
|
||||
}
|
||||
|
@ -519,6 +519,8 @@ public:
|
||||
|
||||
bool IsFloatingFirstLetterChild() const;
|
||||
|
||||
virtual bool UpdateOverflow() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~nsTextFrame();
|
||||
|
||||
@ -552,7 +554,7 @@ protected:
|
||||
SelectionDetails* GetSelectionDetails();
|
||||
|
||||
void UnionAdditionalOverflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aBlockReflowState,
|
||||
nsIFrame* aBlock,
|
||||
PropertyProvider& aProvider,
|
||||
nsRect* aVisualOverflowRect,
|
||||
bool aIncludeTextDecorations);
|
||||
|
@ -6,7 +6,7 @@ skip-if(B2G) == complex-decoration-style-standards.html complex-decoration-style
|
||||
== decoration-style-standards.html decoration-style-standards-ref.html
|
||||
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-quirks-1.html dynamic-underline-vertical-align-quirks-1-ref.html
|
||||
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-standards-1.html dynamic-underline-vertical-align-standards-1-ref.html
|
||||
fails == dynamic-underline-vertical-align-quirks-2.html dynamic-underline-vertical-align-quirks-2-ref.html
|
||||
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-quirks-2.html dynamic-underline-vertical-align-quirks-2-ref.html
|
||||
fuzzy-if(B2G,255,1) == dynamic-underline-vertical-align-standards-2.html dynamic-underline-vertical-align-standards-2-ref.html
|
||||
== line-through-style-block-solid-quirks.html line-through-style-block-quirks-ref.html
|
||||
!= line-through-style-block-dotted-quirks.html line-through-style-block-quirks-ref.html
|
||||
|
@ -2992,17 +2992,11 @@ nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) co
|
||||
uint8_t otherLineStyle = aOther.GetDecorationStyle();
|
||||
if (mTextDecorationLine != aOther.mTextDecorationLine ||
|
||||
lineStyle != otherLineStyle) {
|
||||
// Reflow for decoration line style changes only to or from double or
|
||||
// wave because that may cause overflow area changes
|
||||
if (lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
|
||||
lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY ||
|
||||
otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE ||
|
||||
otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) {
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
}
|
||||
// Repaint for other style decoration lines because they must be in
|
||||
// default overflow rect
|
||||
return NS_STYLE_HINT_VISUAL;
|
||||
nsChangeHint hint = NS_STYLE_HINT_VISUAL;
|
||||
NS_UpdateHint(hint, nsChangeHint_UpdateSubtreeOverflow);
|
||||
return hint;
|
||||
}
|
||||
|
||||
// Repaint for decoration color changes
|
||||
|
@ -1480,7 +1480,9 @@ struct nsStyleTextReset {
|
||||
|
||||
nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
|
||||
static nsChangeHint MaxDifference() {
|
||||
return NS_STYLE_HINT_REFLOW;
|
||||
return nsChangeHint(
|
||||
NS_STYLE_HINT_REFLOW |
|
||||
nsChangeHint_UpdateSubtreeOverflow);
|
||||
}
|
||||
static nsChangeHint MaxDifferenceNeverInherited() {
|
||||
// CalcDifference never returns nsChangeHint_NeedReflow or
|
||||
|
Loading…
Reference in New Issue
Block a user