Commit b0608f67 authored by antti@apple.com's avatar antti@apple.com

Clean up code for getting first line style

https://bugs.webkit.org/show_bug.cgi?id=122037

Reviewed by Andreas Kling.

We have confusing RenderObject::style(bool firstLine). Get rid of it in favour of 
just using RenderObject::firstLineStyle() where appropriate.
        
Also switch to RenderStyle references in many places and move first line style caching
code down to RenderElement.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@156608 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 0e83ab12
2013-09-27 Antti Koivisto <antti@apple.com>
Clean up code for getting first line style
https://bugs.webkit.org/show_bug.cgi?id=122037
Reviewed by Andreas Kling.
We have confusing RenderObject::style(bool firstLine). Get rid of it in favour of
just using RenderObject::firstLineStyle() where appropriate.
Also switch to RenderStyle references in many places and move first line style caching
code down to RenderElement.
2013-09-28 Darin Adler <darin@apple.com>
Add Frame::mainFrame and Frame::isMainFrame
......@@ -44,38 +44,38 @@ EllipsisBox::EllipsisBox(RenderBlock& renderer, const AtomicString& ellipsisStr,
void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
{
GraphicsContext* context = paintInfo.context;
RenderStyle* style = renderer().style(isFirstLineStyle());
Color textColor = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
RenderStyle& lineStyle = this->lineStyle();
Color textColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextFillColor);
if (textColor != context->fillColor())
context->setFillColor(textColor, style->colorSpace());
context->setFillColor(textColor, lineStyle.colorSpace());
bool setShadow = false;
if (style->textShadow()) {
context->setShadow(LayoutSize(style->textShadow()->x(), style->textShadow()->y()),
style->textShadow()->radius(), style->textShadow()->color(), style->colorSpace());
if (lineStyle.textShadow()) {
context->setShadow(LayoutSize(lineStyle.textShadow()->x(), lineStyle.textShadow()->y()),
lineStyle.textShadow()->radius(), lineStyle.textShadow()->color(), lineStyle.colorSpace());
setShadow = true;
}
const Font& font = style->font();
const Font& font = lineStyle.font();
if (selectionState() != RenderObject::SelectionNone) {
paintSelection(context, paintOffset, style, font);
paintSelection(context, paintOffset, &lineStyle, font);
// Select the correct color for painting the text.
Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
if (foreground.isValid() && foreground != textColor)
context->setFillColor(foreground, style->colorSpace());
context->setFillColor(foreground, lineStyle.colorSpace());
}
// FIXME: Why is this always LTR? Fix by passing correct text run flags below.
context->drawText(font, RenderBlock::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + style->fontMetrics().ascent()));
context->drawText(font, RenderBlock::constructTextRun(&renderer(), font, m_str, &lineStyle, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + lineStyle.fontMetrics().ascent()));
// Restore the regular fill color.
if (textColor != context->fillColor())
context->setFillColor(textColor, style->colorSpace());
context->setFillColor(textColor, lineStyle.colorSpace());
if (setShadow)
context->clearShadow();
paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, &lineStyle);
}
InlineBox* EllipsisBox::markupBox() const
......@@ -104,17 +104,17 @@ void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintO
LayoutPoint adjustedPaintOffset = paintOffset;
adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(),
y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent()));
y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent()));
markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
}
IntRect EllipsisBox::selectionRect()
{
RenderStyle* style = renderer().style(isFirstLineStyle());
const Font& font = style->font();
RenderStyle& lineStyle = this->lineStyle();
const Font& font = lineStyle.font();
const RootInlineBox& rootBox = root();
// FIXME: Why is this always LTR? Fix by passing correct text run flags below.
return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + rootBox.selectionTopAdjustedForPrecedingBlock()), rootBox.selectionHeightAdjustedForPrecedingBlock()));
return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(&renderer(), font, m_str, &lineStyle, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + rootBox.selectionTopAdjustedForPrecedingBlock()), rootBox.selectionHeightAdjustedForPrecedingBlock()));
}
void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& paintOffset, RenderStyle* style, const Font& font)
......@@ -147,9 +147,9 @@ bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Hit test the markup box.
if (InlineBox* markupBox = this->markupBox()) {
RenderStyle* style = renderer().style(isFirstLineStyle());
RenderStyle& lineStyle = this->lineStyle();
LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent());
LayoutUnit mty = adjustedLocation.y() + lineStyle.fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent());
if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
renderer().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
return true;
......
......@@ -140,15 +140,16 @@ float InlineBox::logicalHeight() const
{
if (hasVirtualLogicalHeight())
return virtualLogicalHeight();
const RenderStyle& lineStyle = this->lineStyle();
if (renderer().isTextOrLineBreak())
return behavesLikeText() ? renderer().style(isFirstLineStyle())->fontMetrics().height() : 0;
return behavesLikeText() ? lineStyle.fontMetrics().height() : 0;
if (renderer().isBox() && parent())
return isHorizontal() ? toRenderBox(renderer()).height() : toRenderBox(renderer()).width();
ASSERT(isInlineFlowBox());
RenderBoxModelObject* flowObject = boxModelObject();
const FontMetrics& fontMetrics = renderer().style(isFirstLineStyle())->fontMetrics();
const FontMetrics& fontMetrics = lineStyle.fontMetrics();
float result = fontMetrics.height();
if (parent())
result += flowObject->borderAndPaddingLogicalHeight();
......
......@@ -151,8 +151,8 @@ public:
void setExtracted(bool extracted = true) { m_bitfields.setExtracted(extracted); }
void setFirstLineStyleBit(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
bool isFirstLineStyle() const { return m_bitfields.firstLine(); }
void setIsFirstLine(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
bool isFirstLine() const { return m_bitfields.firstLine(); }
void remove();
......@@ -279,8 +279,10 @@ public:
int expansion() const { return m_bitfields.expansion(); }
bool visibleToHitTesting() const { return renderer().style()->visibility() == VISIBLE && renderer().style()->pointerEvents() != PE_NONE; }
RenderStyle& lineStyle() const { return m_bitfields.firstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
EVerticalAlign verticalAlign() const { return renderer().style(m_bitfields.firstLine())->verticalAlign(); }
EVerticalAlign verticalAlign() const { return lineStyle().verticalAlign(); }
// Use with caution! The type is not checked!
RenderBoxModelObject* boxModelObject() const
......
This diff is collapsed.
......@@ -73,6 +73,7 @@ public:
#endif
RenderBoxModelObject& renderer() const { return toRenderBoxModelObject(InlineBox::renderer()); }
RenderStyle& lineStyle() const { return isFirstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
......@@ -142,13 +143,13 @@ public:
{
if (!includeLogicalLeftEdge())
return 0;
return isHorizontal() ? renderer().style(isFirstLineStyle())->borderLeftWidth() : renderer().style(isFirstLineStyle())->borderTopWidth();
return isHorizontal() ? lineStyle().borderLeftWidth() : lineStyle().borderTopWidth();
}
int borderLogicalRight() const
{
if (!includeLogicalRightEdge())
return 0;
return isHorizontal() ? renderer().style(isFirstLineStyle())->borderRightWidth() : renderer().style(isFirstLineStyle())->borderBottomWidth();
return isHorizontal() ? lineStyle().borderRightWidth() : lineStyle().borderBottomWidth();
}
int paddingLogicalLeft() const
{
......
This diff is collapsed.
......@@ -58,6 +58,7 @@ public:
}
RenderText& renderer() const { return toRenderText(InlineBox::renderer()); }
RenderStyle& lineStyle() const { return isFirstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
virtual void destroy(RenderArena&) OVERRIDE FINAL;
......
......@@ -5615,7 +5615,7 @@ LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction,
return RenderBox::lineHeight(firstLine, direction, linePositionMode);
if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
RenderStyle* s = firstLine ? firstLineStyle() : style();
if (s != style())
return s->computedLineHeight(&view());
}
......@@ -5658,7 +5658,8 @@ int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, Lin
return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
}
const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
const RenderStyle* style = firstLine ? firstLineStyle() : this->style();
const FontMetrics& fontMetrics = style->fontMetrics();
return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
}
......@@ -5667,7 +5668,8 @@ LayoutUnit RenderBlock::minLineHeightForReplacedRenderer(bool isFirstLine, Layou
if (!document().inNoQuirksMode() && replacedHeight)
return replacedHeight;
if (!(style(isFirstLine)->lineBoxContain() & LineBoxContainBlock))
const RenderStyle* style = isFirstLine ? firstLineStyle() : this->style();
if (!(style->lineBoxContain() & LineBoxContainBlock))
return 0;
return std::max<LayoutUnit>(replacedHeight, lineHeight(isFirstLine, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
......@@ -5680,7 +5682,7 @@ int RenderBlock::firstLineBoxBaseline() const
if (childrenInline()) {
if (firstLineBox())
return firstLineBox()->logicalTop() + style(true)->fontMetrics().ascent(firstRootBox()->baselineType());
return firstLineBox()->logicalTop() + firstLineStyle()->fontMetrics().ascent(firstRootBox()->baselineType());
else
return -1;
}
......@@ -5714,8 +5716,11 @@ int RenderBlock::lastLineBoxBaseline(LineDirectionMode lineDirection) const
+ (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
+ (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
}
if (lastLineBox())
return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->fontMetrics().ascent(lastRootBox()->baselineType());
if (lastLineBox()) {
bool isFirstLine = lastLineBox() == firstLineBox();
RenderStyle* style = isFirstLine ? firstLineStyle() : this->style();
return lastLineBox()->logicalTop() + style->fontMetrics().ascent(lastRootBox()->baselineType());
}
return -1;
} else {
bool haveNormalFlowChild = false;
......
......@@ -381,7 +381,7 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, const LineInfo& l
InlineBox* newBox = createInlineBoxForRenderer(obj, obj == this);
ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox());
parentBox = toInlineFlowBox(newBox);
parentBox->setFirstLineStyleBit(lineInfo.isFirstLine());
parentBox->setIsFirstLine(lineInfo.isFirstLine());
parentBox->setIsHorizontal(isHorizontalWritingMode());
if (!hasDefaultLineBoxContain)
parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
......@@ -622,13 +622,18 @@ public:
HashSet<const SimpleFontData*> fallbackFonts;
};
static inline RenderStyle& lineStyle(RenderElement& renderer, const LineInfo& lineInfo)
{
return lineInfo.isFirstLine() ? *renderer.firstLineStyle() : *renderer.style();
}
static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo,
GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
{
HashSet<const SimpleFontData*> fallbackFonts;
GlyphOverflow glyphOverflow;
const Font& font = renderer->style(lineInfo.isFirstLine())->font();
const Font& font = lineStyle(*renderer->parent(), lineInfo).font();
// Always compute glyph overflow if the block's line-box-contain value is "glyphs".
if (lineBox->fitsToGlyphs()) {
// If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
......@@ -644,10 +649,9 @@ static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* ru
}
LayoutUnit hyphenWidth = 0;
if (toInlineTextBox(run->m_box)->hasHyphen()) {
const Font& font = renderer->style(lineInfo.isFirstLine())->font();
if (toInlineTextBox(run->m_box)->hasHyphen())
hyphenWidth = measureHyphenWidth(renderer, font, &fallbackFonts);
}
float measuredWidth = 0;
bool kerningIsEnabled = font.typesettingFeatures() & Kerning;
......@@ -912,7 +916,7 @@ BidiRun* RenderBlock::computeInlineDirectionPositionsForSegment(RootInlineBox* l
if (int length = rt->textLength()) {
if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().wordSpacing();
totalLogicalWidth += lineStyle(*rt->parent(), lineInfo).font().wordSpacing();
needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1)) && r->m_stop == length;
}
......@@ -2214,12 +2218,15 @@ static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const Line
static bool requiresLineBoxForContent(RenderInline* flow, const LineInfo& lineInfo)
{
RenderObject* parent = flow->parent();
if (flow->document().inNoQuirksMode()
&& (flow->style(lineInfo.isFirstLine())->lineHeight() != parent->style(lineInfo.isFirstLine())->lineHeight()
|| flow->style()->verticalAlign() != parent->style()->verticalAlign()
|| !parent->style()->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flow->style()->font().fontMetrics())))
RenderElement* parent = flow->parent();
if (flow->document().inNoQuirksMode()) {
const RenderStyle& flowStyle = lineStyle(*flow, lineInfo);
const RenderStyle& parentStyle = lineStyle(*parent, lineInfo);
if (flowStyle.lineHeight() != parentStyle.lineHeight()
|| flowStyle.verticalAlign() != parentStyle.verticalAlign()
|| !parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flowStyle.font().fontMetrics()))
return true;
}
return false;
}
......@@ -2905,10 +2912,10 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
}
}
RenderStyle* style = t->style(lineInfo.isFirstLine());
const Font& f = style->font();
RenderStyle& style = lineStyle(*t->parent(), lineInfo);
const Font& f = style.font();
bool isFixedPitch = f.isFixedPitch();
bool canHyphenate = style->hyphens() == HyphensAuto && WebCore::canHyphenate(style->locale());
bool canHyphenate = style.hyphens() == HyphensAuto && WebCore::canHyphenate(style.locale());
unsigned lastSpace = current.m_pos;
float wordSpacing = currentStyle->wordSpacing();
......@@ -2936,7 +2943,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
renderTextInfo.m_text = t;
renderTextInfo.m_font = &f;
renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style->locale());
renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style.locale());
} else if (renderTextInfo.m_layout && renderTextInfo.m_font != &f) {
renderTextInfo.m_font = &f;
renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
......@@ -2947,7 +2954,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
// Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
// words with their trailing space, then subtract its width.
HashSet<const SimpleFontData*> fallbackFonts;
float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(RenderBlock::constructTextRun(t, f, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(RenderBlock::constructTextRun(t, f, &space, 1, &style), &fallbackFonts) + wordSpacing : 0;
UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharacter();
UChar secondToLastCharacter = renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
......@@ -2960,7 +2967,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
if (!collapseWhiteSpace || !currentCharacterIsSpace)
lineInfo.setEmpty(false, m_block, &width);
if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) {
if (c == softHyphen && autoWrap && !hyphenWidth && style.hyphens() != HyphensNone) {
hyphenWidth = measureHyphenWidth(t, f, &fallbackFonts);
width.addUncommittedWidth(hyphenWidth, *current.m_obj);
}
......@@ -2977,7 +2984,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
}
bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
&& (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
&& (style.hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
if (betweenWords || midWordBreak) {
bool stoppedIgnoringSpaces = false;
......@@ -3054,7 +3061,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
}
if (lineWasTooWide || !width.fitsOnLine()) {
if (canHyphenate && !width.fitsOnLine()) {
tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTempWidth, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
tryHyphenating(t, f, style.locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTempWidth, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
if (m_hyphenated)
goto end;
}
......@@ -3065,7 +3072,7 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
lineInfo.setPreviousLineBrokeCleanly(true);
wordMeasurement.endOffset = lBreak.m_pos;
}
if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characterAt(lBreak.m_pos - 1) == softHyphen && style->hyphens() != HyphensNone)
if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characterAt(lBreak.m_pos - 1) == softHyphen && style.hyphens() != HyphensNone)
m_hyphenated = true;
if (lBreak.m_pos && lBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
if (charWidth) {
......@@ -3206,9 +3213,9 @@ InlineIterator LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineI
if (!width.fitsOnLine()) {
if (canHyphenate)
tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTempWidth, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
tryHyphenating(t, f, style.locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style.hyphenationLimitBefore(), style.hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTempWidth, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style->hyphens() != HyphensNone)
if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style.hyphens() != HyphensNone)
m_hyphenated = true;
if (m_hyphenated)
......
......@@ -1008,7 +1008,8 @@ void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool
const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
const Font& font = style(numVisibleLines == 1)->font();
const RenderStyle& lineStyle = numVisibleLines == 1 ? *firstLineStyle() : *style();
const Font& font = lineStyle.font();
// Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
LayoutUnit totalWidth;
......
......@@ -53,6 +53,7 @@
#include "RenderText.h"
#include "RenderView.h"
#include "SVGRenderSupport.h"
#include "StyleResolver.h"
#if USE(ACCELERATED_COMPOSITING)
#include "RenderLayerCompositor.h"
......@@ -175,6 +176,56 @@ RenderElement* RenderElement::createFor(Element& element, RenderStyle& style)
return nullptr;
}
enum StyleCacheState {
Cached,
Uncached
};
static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheState type, const RenderObject* renderer, RenderStyle* style)
{
const RenderObject* rendererForFirstLineStyle = renderer;
if (renderer->isBeforeOrAfterContent())
rendererForFirstLineStyle = renderer->parent();
if (rendererForFirstLineStyle->isRenderBlockFlow() || rendererForFirstLineStyle->isRenderButton()) {
if (RenderBlock* firstLineBlock = rendererForFirstLineStyle->firstLineBlock()) {
if (type == Cached)
return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == renderer ? style : 0);
}
} else if (!rendererForFirstLineStyle->isAnonymous() && rendererForFirstLineStyle->isRenderInline()) {
RenderStyle* parentStyle = rendererForFirstLineStyle->parent()->firstLineStyle();
if (parentStyle != rendererForFirstLineStyle->parent()->style()) {
if (type == Cached) {
// A first-line style is in effect. Cache a first-line style for ourselves.
rendererForFirstLineStyle->style()->setHasPseudoStyle(FIRST_LINE_INHERITED);
return rendererForFirstLineStyle->getCachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle);
}
return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), parentStyle, style);
}
}
return 0;
}
PassRefPtr<RenderStyle> RenderElement::uncachedFirstLineStyle(RenderStyle* style) const
{
if (!document().styleSheetCollection().usesFirstLineRules())
return 0;
return firstLineStyleForCachedUncachedType(Uncached, this, style);
}
RenderStyle* RenderElement::cachedFirstLineStyle() const
{
ASSERT(document().styleSheetCollection().usesFirstLineRules());
RenderStyle* style = this->style();
if (RefPtr<RenderStyle> firstLineStyle = firstLineStyleForCachedUncachedType(Cached, this, style))
return firstLineStyle.get();
return style;
}
StyleDifference RenderElement::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
{
#if USE(ACCELERATED_COMPOSITING)
......
......@@ -34,7 +34,7 @@ public:
static RenderElement* createFor(Element&, RenderStyle&);
RenderStyle* style() const { return m_style.get(); }
RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
RenderStyle* firstLineStyle() const;
virtual void setStyle(PassRefPtr<RenderStyle>);
// Called to update a style that is allowed to trigger animations.
......@@ -72,6 +72,10 @@ public:
// Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isRoot() is true.
RenderElement* rendererForRootBackground();
// Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
// given new style, without accessing the cache.
PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
// Updates only the local style ptr of the object. Does not update the state of the object,
// and so only should be called when the style is known not to have changed (or from setStyle).
void setStyleInternal(PassRefPtr<RenderStyle> style) { m_style = style; }
......@@ -118,6 +122,7 @@ private:
#endif
StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
RenderStyle* cachedFirstLineStyle() const;
RenderObject* m_firstChild;
RenderObject* m_lastChild;
......@@ -130,6 +135,11 @@ private:
static bool s_noLongerAffectsParentBlock;
};
inline RenderStyle* RenderElement::firstLineStyle() const
{
return document().styleSheetCollection().usesFirstLineRules() ? cachedFirstLineStyle() : style();
}
inline LayoutUnit RenderElement::valueForLength(const Length& length, LayoutUnit maximumValue, bool roundPercentages) const
{
return WebCore::valueForLength(length, maximumValue, &view(), roundPercentages);
......@@ -175,6 +185,13 @@ inline RenderStyle* RenderObject::style() const
return toRenderElement(this)->style();
}
inline RenderStyle* RenderObject::firstLineStyle() const
{
if (isText())
return m_parent->firstLineStyle();
return toRenderElement(this)->firstLineStyle();
}
inline RenderElement* Element::renderer() const
{
return toRenderElement(Node::renderer());
......
......@@ -224,11 +224,11 @@ void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
if (!alwaysCreateLineBoxes && checkFonts && document().styleSheetCollection().usesFirstLineRules()) {
// Have to check the first line style as well.
parentStyle = parent()->style(true);
RenderStyle* childStyle = style(true);
parentStyle = parent()->firstLineStyle();
RenderStyle* childStyle = firstLineStyle();
alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
|| childStyle->verticalAlign() != BASELINE
|| parentStyle->lineHeight() != childStyle->lineHeight();
|| childStyle->verticalAlign() != BASELINE
|| parentStyle->lineHeight() != childStyle->lineHeight();
}
if (alwaysCreateLineBoxes) {
......@@ -570,8 +570,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
RenderBox* currBox = toRenderBox(curr);
if (currBox->inlineBoxWrapper()) {
const RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root();
int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
int logicalHeight = containerStyle.font().fontMetrics().height();
if (isHorizontal)
yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginWidth(), logicalHeight));
else
......@@ -585,8 +586,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
else {
for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
const RootInlineBox& rootBox = childLine->root();
int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
int logicalHeight = containerStyle.fontMetrics().height();
if (isHorizontal)
yield(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
logicalTop,
......@@ -603,8 +605,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
RenderText* currText = toRenderText(curr);
for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
const RootInlineBox& rootBox = childText->root();
int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
int logicalHeight = containerStyle.font().fontMetrics().height();
if (isHorizontal)
yield(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
else
......@@ -614,8 +617,9 @@ void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const Ren
if (InlineBox* inlineBox = toRenderLineBreak(curr)->inlineBoxWrapper()) {
// FIXME: This could use a helper to share these with text path.
const RootInlineBox& rootBox = inlineBox->root();
int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
int logicalHeight = containerStyle.fontMetrics().height();
if (isHorizontal)
yield(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
else
......@@ -1352,9 +1356,9 @@ InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
{
if