Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Missing underline after the first character in contenteditable
https://bugs.webkit.org/show_bug.cgi?id=255357
<rdar://107846703>

Reviewed by Antti Koivisto.

RenderText's m_min/m_maxWidth values become stale when we dynamically switch over to IFC preferred width computation.
(and sadly these (cached) values are consulted when RenderText::width is called with [0, text-length] range).

* Source/WebCore/rendering/RenderBlockFlow.cpp:
(WebCore::RenderBlockFlow::tryComputePreferredWidthsUsingModernPath):
* Source/WebCore/rendering/RenderCounter.cpp:
(WebCore::RenderCounter::computePreferredLogicalWidths): (forcedMinMaxWidthComputation is to suppress ASSERT)
* Source/WebCore/rendering/RenderCounter.h:
* Source/WebCore/rendering/RenderText.cpp:
(WebCore::RenderText::minLogicalWidth const):
(WebCore::RenderText::maxLogicalWidth const):
(WebCore::RenderText::computePreferredLogicalWidths):
(WebCore::RenderText::width const):
* Source/WebCore/rendering/RenderText.h:
(WebCore::RenderText::resetMinMaxWidth):

Canonical link: https://commits.webkit.org/262914@main
  • Loading branch information
alanbaradlay committed Apr 13, 2023
1 parent 563b555 commit 3904de1
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 13 deletions.
8 changes: 6 additions & 2 deletions Source/WebCore/rendering/RenderBlockFlow.cpp
Expand Up @@ -4927,8 +4927,12 @@ bool RenderBlockFlow::tryComputePreferredWidthsUsingModernPath(LayoutUnit& minLo
modernLineLayout()->updateInlineContentDimensions();

std::tie(minLogicalWidth, maxLogicalWidth) = modernLineLayout()->computeIntrinsicWidthConstraints();
for (auto walker = InlineWalker(*this); !walker.atEnd(); walker.advance())
walker.current()->setPreferredLogicalWidthsDirty(false);
for (auto walker = InlineWalker(*this); !walker.atEnd(); walker.advance()) {
auto* renderer = walker.current();
renderer->setPreferredLogicalWidthsDirty(false);
if (auto* renderText = dynamicDowncast<RenderText>(renderer))
renderText->resetMinMaxWidth();
}
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/rendering/RenderCounter.cpp
Expand Up @@ -485,7 +485,7 @@ void RenderCounter::updateCounter()
computePreferredLogicalWidths(0);
}

void RenderCounter::computePreferredLogicalWidths(float lead)
void RenderCounter::computePreferredLogicalWidths(float lead, bool forcedMinMaxWidthComputation)
{
// FIXME: We shouldn't be modifying the tree in computePreferredLogicalWidths.
// Instead, we should properly hook the appropriate changes in the DOM and modify
Expand All @@ -496,7 +496,7 @@ void RenderCounter::computePreferredLogicalWidths(float lead)

setRenderedText(originalText());

RenderText::computePreferredLogicalWidths(lead);
RenderText::computePreferredLogicalWidths(lead, forcedMinMaxWidthComputation);
}

static void destroyCounterNodeWithoutMapRemoval(const AtomString& identifier, CounterNode& node)
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/rendering/RenderCounter.h
Expand Up @@ -53,7 +53,7 @@ class RenderCounter final : public RenderText {
bool isCounter() const override;
String originalText() const override;

void computePreferredLogicalWidths(float leadWidth) override;
void computePreferredLogicalWidths(float leadWidth, bool forcedMinMaxWidthComputation = false) override;

RefPtr<CSSCounterStyle> counterStyle() const;

Expand Down
15 changes: 9 additions & 6 deletions Source/WebCore/rendering/RenderText.cpp
Expand Up @@ -904,15 +904,15 @@ static inline bool isSpaceAccordingToStyle(UChar c, const RenderStyle& style)
float RenderText::minLogicalWidth() const
{
if (preferredLogicalWidthsDirty() || !m_minWidth)
const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, !preferredLogicalWidthsDirty());

return *m_minWidth;
}

float RenderText::maxLogicalWidth() const
{
if (preferredLogicalWidthsDirty() || !m_maxWidth)
const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, !preferredLogicalWidthsDirty());

return *m_maxWidth;
}
Expand All @@ -935,11 +935,11 @@ LineBreakIteratorMode mapLineBreakToIteratorMode(LineBreak lineBreak)
return LineBreakIteratorMode::Default;
}

void RenderText::computePreferredLogicalWidths(float leadWidth)
void RenderText::computePreferredLogicalWidths(float leadWidth, bool forcedMinMaxWidthComputation)
{
HashSet<const Font*> fallbackFonts;
GlyphOverflow glyphOverflow;
computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow, forcedMinMaxWidthComputation);
if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom)
m_knownToHaveNoOverflowAndNoFallbackFonts = true;
}
Expand Down Expand Up @@ -1004,9 +1004,9 @@ float RenderText::maxWordFragmentWidth(const RenderStyle& style, const FontCasca
return std::max(maxFragmentWidth, suffixWidth);
}

void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow& glyphOverflow)
void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow& glyphOverflow, bool forcedMinMaxWidthComputation)
{
ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
ASSERT_UNUSED(forcedMinMaxWidthComputation, m_hasTab || preferredLogicalWidthsDirty() || forcedMinMaxWidthComputation || !m_knownToHaveNoOverflowAndNoFallbackFonts);

m_minWidth = 0;
m_beginMinWidth = 0;
Expand Down Expand Up @@ -1642,6 +1642,9 @@ float RenderText::width(unsigned from, unsigned length, const FontCascade& fontC
if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
m_knownToHaveNoOverflowAndNoFallbackFonts = true;
}
// The rare case of when we switch between IFC and legacy preferred width computation.
if (!m_maxWidth)
width = maxLogicalWidth();
width = *m_maxWidth;
} else
width = maxLogicalWidth();
Expand Down
12 changes: 10 additions & 2 deletions Source/WebCore/rendering/RenderText.h
Expand Up @@ -182,8 +182,10 @@ class RenderText : public RenderObject {

static std::optional<bool> emphasisMarkExistsAndIsAbove(const RenderText&, const RenderStyle&);

void resetMinMaxWidth();

protected:
virtual void computePreferredLogicalWidths(float leadWidth);
virtual void computePreferredLogicalWidths(float leadWidth, bool forcedMinMaxWidthComputation = false);
void willBeDestroyed() override;

virtual void setRenderedText(const String&);
Expand All @@ -206,7 +208,7 @@ class RenderText : public RenderObject {
LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) final;
LayoutRect clippedOverflowRect(const RenderLayerModelObject* repaintContainer, VisibleRectContext) const final;

void computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow&);
void computePreferredLogicalWidths(float leadWidth, HashSet<const Font*>& fallbackFonts, GlyphOverflow&, bool forcedMinMaxWidthComputation = false);

bool computeCanUseSimpleFontCodePath() const;

Expand Down Expand Up @@ -316,6 +318,12 @@ inline RenderText* Text::renderer() const
return downcast<RenderText>(Node::renderer());
}

inline void RenderText::resetMinMaxWidth()
{
m_minWidth = { };
m_maxWidth = { };
}

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderText, isText())

0 comments on commit 3904de1

Please sign in to comment.