Bug 1324618 part 8. Implement restyling for first-letter frames. r?emilio
MozReview-Commit-ID: IPUDD1Q6AFq
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -11710,17 +11710,18 @@ nsCSSFrameConstructor::CreateLetterFrame
nsContainerFrame* aParentFrame,
nsFrameItems& aResult)
{
NS_PRECONDITION(aTextContent->IsNodeOfType(nsINode::eTEXT),
"aTextContent isn't text");
NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
"Not a block frame?");
- // Get style context for the first-letter-frame
+ // Get style context for the first-letter-frame. Keep this in sync with
+ // nsBlockFrame::UpdatePseudoElementStyles.
nsStyleContext* parentStyleContext =
nsFrame::CorrectStyleParentFrame(aParentFrame,
nsCSSPseudoElements::firstLetter)->
StyleContext();
// Use content from containing block so that we can actually
// find a matching style rule.
nsIContent* blockContent = aBlockFrame->GetContent();
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -5620,16 +5620,56 @@ nsBlockInFlowLineIterator::nsBlockInFlow
nsBlockInFlowLineIterator::nsBlockInFlowLineIterator(nsBlockFrame* aFrame,
bool* aFoundValidLine)
: mFrame(aFrame), mLineList(&aFrame->mLines)
{
mLine = aFrame->LinesBegin();
*aFoundValidLine = FindValidLine();
}
+void
+nsBlockFrame::UpdateFirstLetterStyle(nsIFrame* aLetterFrame,
+ ServoRestyleState& aRestyleState)
+{
+ // Figure out what the right style parent is. This needs to match
+ // nsCSSFrameConstructor::CreateLetterFrame.
+ nsIFrame* inFlowFrame = aLetterFrame;
+ if (inFlowFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
+ inFlowFrame = inFlowFrame->GetPlaceholderFrame();
+ }
+ nsIFrame* styleParent =
+ CorrectStyleParentFrame(inFlowFrame->GetParent(),
+ nsCSSPseudoElements::firstLetter);
+ nsStyleContext* parentStyle = styleParent->StyleContext();
+ RefPtr<nsStyleContext> firstLetterStyle =
+ aRestyleState.StyleSet()
+ .ResolvePseudoElementStyle(mContent->AsElement(),
+ CSSPseudoElementType::firstLetter,
+ parentStyle,
+ nullptr);
+ // Note that we don't need to worry about changehints for the continuation
+ // styles: those will be handled by the styleParent already.
+ RefPtr<nsStyleContext> continuationStyle =
+ aRestyleState.StyleSet().ResolveStyleForFirstLetterContinuation(parentStyle);
+ UpdateStyleOfOwnedChildFrame(aLetterFrame, firstLetterStyle, aRestyleState,
+ Some(continuationStyle.get()));
+
+ // We also want to update the style on the textframe inside the first-letter.
+ // We don't need to compute a changehint for this, though, since any changes
+ // to it are handled by the first-letter anyway.
+ nsIFrame* textFrame = aLetterFrame->PrincipalChildList().FirstChild();
+ RefPtr<nsStyleContext> firstTextStyle =
+ aRestyleState.StyleSet().ResolveStyleForText(textFrame->GetContent(),
+ firstLetterStyle);
+ textFrame->SetStyleContext(firstTextStyle);
+
+ // We don't need to update style for textFrame's continuations: it's already
+ // set up to inherit from parentStyle, which is what we want.
+}
+
static nsIFrame*
FindChildContaining(nsBlockFrame* aFrame, nsIFrame* aFindFrame)
{
NS_ASSERTION(aFrame, "must have frame");
nsIFrame* child;
while (true) {
nsIFrame* block = aFrame;
do {
@@ -7519,16 +7559,20 @@ void
nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState)
{
if (nsBulletFrame* bullet = GetBullet()) {
CSSPseudoElementType type = bullet->StyleContext()->GetPseudoType();
RefPtr<nsStyleContext> newBulletStyle =
ResolveBulletStyle(type, &aRestyleState.StyleSet());
UpdateStyleOfOwnedChildFrame(bullet, newBulletStyle, aRestyleState);
}
+
+ if (nsIFrame* firstLetter = GetFirstLetter()) {
+ UpdateFirstLetterStyle(firstLetter, aRestyleState);
+ }
}
already_AddRefed<nsStyleContext>
nsBlockFrame::ResolveBulletStyle(CSSPseudoElementType aType,
StyleSetHandle aStyleSet)
{
nsStyleContext* parentStyle =
CorrectStyleParentFrame(this,
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -918,16 +918,20 @@ protected:
// Resolve a style context for our bullet frame. aType should be
// mozListBullet or mozListNumber. Passing in the style set is an
// optimization, because all callsites have it.
already_AddRefed<nsStyleContext> ResolveBulletStyle(
mozilla::CSSPseudoElementType aType,
mozilla::StyleSetHandle aStyleSet);
+ // Update our first-letter styles during stylo post-traversal.
+ void UpdateFirstLetterStyle(nsIFrame* aLetterFrame,
+ mozilla::ServoRestyleState& aRestyleState);
+
#ifdef DEBUG
void VerifyLines(bool aFinalCheckOK);
void VerifyOverflowSituation();
int32_t GetDepth() const;
#endif
nscoord mMinWidth, mPrefWidth;