Changeset 156608 in webkit


Ignore:
Timestamp:
Sep 28, 2013 11:30:16 AM (11 years ago)
Author:
Antti Koivisto
Message:

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.

Location:
trunk/Source/WebCore
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r156607 r156608  
     12013-09-27  Antti Koivisto  <antti@apple.com>
     2
     3        Clean up code for getting first line style
     4        https://bugs.webkit.org/show_bug.cgi?id=122037
     5
     6        Reviewed by Andreas Kling.
     7
     8        We have confusing RenderObject::style(bool firstLine). Get rid of it in favour of
     9        just using RenderObject::firstLineStyle() where appropriate.
     10       
     11        Also switch to RenderStyle references in many places and move first line style caching
     12        code down to RenderElement.
     13
    1142013-09-28  Darin Adler  <darin@apple.com>
    215
  • trunk/Source/WebCore/rendering/EllipsisBox.cpp

    r156095 r156608  
    4545{
    4646    GraphicsContext* context = paintInfo.context;
    47     RenderStyle* style = renderer().style(isFirstLineStyle());
    48     Color textColor = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
     47    RenderStyle& lineStyle = this->lineStyle();
     48    Color textColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextFillColor);
    4949    if (textColor != context->fillColor())
    50         context->setFillColor(textColor, style->colorSpace());
     50        context->setFillColor(textColor, lineStyle.colorSpace());
    5151    bool setShadow = false;
    52     if (style->textShadow()) {
    53         context->setShadow(LayoutSize(style->textShadow()->x(), style->textShadow()->y()),
    54                            style->textShadow()->radius(), style->textShadow()->color(), style->colorSpace());
     52    if (lineStyle.textShadow()) {
     53        context->setShadow(LayoutSize(lineStyle.textShadow()->x(), lineStyle.textShadow()->y()),
     54            lineStyle.textShadow()->radius(), lineStyle.textShadow()->color(), lineStyle.colorSpace());
    5555        setShadow = true;
    5656    }
    5757
    58     const Font& font = style->font();
     58    const Font& font = lineStyle.font();
    5959    if (selectionState() != RenderObject::SelectionNone) {
    60         paintSelection(context, paintOffset, style, font);
     60        paintSelection(context, paintOffset, &lineStyle, font);
    6161
    6262        // Select the correct color for painting the text.
    6363        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
    6464        if (foreground.isValid() && foreground != textColor)
    65             context->setFillColor(foreground, style->colorSpace());
     65            context->setFillColor(foreground, lineStyle.colorSpace());
    6666    }
    6767
    6868    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
    69     context->drawText(font, RenderBlock::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + style->fontMetrics().ascent()));
     69    context->drawText(font, RenderBlock::constructTextRun(&renderer(), font, m_str, &lineStyle, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + lineStyle.fontMetrics().ascent()));
    7070
    7171    // Restore the regular fill color.
    7272    if (textColor != context->fillColor())
    73         context->setFillColor(textColor, style->colorSpace());
     73        context->setFillColor(textColor, lineStyle.colorSpace());
    7474
    7575    if (setShadow)
    7676        context->clearShadow();
    7777
    78     paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
     78    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, &lineStyle);
    7979}
    8080
     
    105105    LayoutPoint adjustedPaintOffset = paintOffset;
    106106    adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(),
    107         y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent()));
     107        y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent()));
    108108    markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
    109109}
     
    111111IntRect EllipsisBox::selectionRect()
    112112{
    113     RenderStyle* style = renderer().style(isFirstLineStyle());
    114     const Font& font = style->font();
     113    RenderStyle& lineStyle = this->lineStyle();
     114    const Font& font = lineStyle.font();
    115115    const RootInlineBox& rootBox = root();
    116116    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
    117     return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(&renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + rootBox.selectionTopAdjustedForPrecedingBlock()), rootBox.selectionHeightAdjustedForPrecedingBlock()));
     117    return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(&renderer(), font, m_str, &lineStyle, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + rootBox.selectionTopAdjustedForPrecedingBlock()), rootBox.selectionHeightAdjustedForPrecedingBlock()));
    118118}
    119119
     
    148148    // Hit test the markup box.
    149149    if (InlineBox* markupBox = this->markupBox()) {
    150         RenderStyle* style = renderer().style(isFirstLineStyle());
     150        RenderStyle& lineStyle = this->lineStyle();
    151151        LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
    152         LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer().style(isFirstLineStyle())->fontMetrics().ascent());
     152        LayoutUnit mty = adjustedLocation.y() + lineStyle.fontMetrics().ascent() - (markupBox->y() + markupBox->lineStyle().fontMetrics().ascent());
    153153        if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
    154154            renderer().updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
  • trunk/Source/WebCore/rendering/InlineBox.cpp

    r156054 r156608  
    141141    if (hasVirtualLogicalHeight())
    142142        return virtualLogicalHeight();
    143    
     143
     144    const RenderStyle& lineStyle = this->lineStyle();
    144145    if (renderer().isTextOrLineBreak())
    145         return behavesLikeText() ? renderer().style(isFirstLineStyle())->fontMetrics().height() : 0;
     146        return behavesLikeText() ? lineStyle.fontMetrics().height() : 0;
    146147    if (renderer().isBox() && parent())
    147148        return isHorizontal() ? toRenderBox(renderer()).height() : toRenderBox(renderer()).width();
     
    149150    ASSERT(isInlineFlowBox());
    150151    RenderBoxModelObject* flowObject = boxModelObject();
    151     const FontMetrics& fontMetrics = renderer().style(isFirstLineStyle())->fontMetrics();
     152    const FontMetrics& fontMetrics = lineStyle.fontMetrics();
    152153    float result = fontMetrics.height();
    153154    if (parent())
  • trunk/Source/WebCore/rendering/InlineBox.h

    r156038 r156608  
    152152    void setExtracted(bool extracted = true) { m_bitfields.setExtracted(extracted); }
    153153   
    154     void setFirstLineStyleBit(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
    155     bool isFirstLineStyle() const { return m_bitfields.firstLine(); }
     154    void setIsFirstLine(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
     155    bool isFirstLine() const { return m_bitfields.firstLine(); }
    156156
    157157    void remove();
     
    280280
    281281    bool visibleToHitTesting() const { return renderer().style()->visibility() == VISIBLE && renderer().style()->pointerEvents() != PE_NONE; }
    282    
    283     EVerticalAlign verticalAlign() const { return renderer().style(m_bitfields.firstLine())->verticalAlign(); }
     282
     283    RenderStyle& lineStyle() const { return m_bitfields.firstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
     284   
     285    EVerticalAlign verticalAlign() const { return lineStyle().verticalAlign(); }
    284286
    285287    // Use with caution! The type is not checked!
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r156285 r156608  
    110110        m_lastChild = child;
    111111    }
    112     child->setFirstLineStyleBit(isFirstLineStyle());
     112    child->setIsFirstLine(isFirstLine());
    113113    child->setIsHorizontal(isHorizontal());
    114114    if (child->behavesLikeText()) {
     
    122122
    123123    if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer().isOutOfFlowPositioned()) {
    124         RenderStyle* parentStyle = renderer().style(isFirstLineStyle());
    125         RenderStyle* childStyle = child->renderer().style(isFirstLineStyle());
     124        const RenderStyle& parentStyle = lineStyle();
     125        const RenderStyle& childStyle = child->lineStyle();
    126126        bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
    127127        if (child->renderer().isReplaced())
     
    129129        else if (child->behavesLikeText()) {
    130130            if (child->renderer().isLineBreak() || child->renderer().parent() != &renderer()) {
    131                 if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
    132                     || parentStyle->lineHeight() != childStyle->lineHeight()
    133                     || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
     131                if (!parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.font().fontMetrics())
     132                    || parentStyle.lineHeight() != childStyle.lineHeight()
     133                    || (parentStyle.verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle.verticalAlign() != BASELINE)
    134134                    shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    135135            }
    136             if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
     136            if (childStyle.hasTextCombine() || childStyle.textEmphasisMark() != TextEmphasisMarkNone)
    137137                shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    138138        } else {
     
    146146                // Check the child's bit, and then also check for differences in font, line-height, vertical-align
    147147                if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline()
    148                     || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
    149                     || parentStyle->lineHeight() != childStyle->lineHeight()
    150                     || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE
    151                     || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine())
     148                    || !parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle.font().fontMetrics())
     149                    || parentStyle.lineHeight() != childStyle.lineHeight()
     150                    || (parentStyle.verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle.verticalAlign() != BASELINE
     151                    || childStyle.hasBorder() || childStyle.hasPadding() || childStyle.hasTextCombine())
    152152                    shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    153153            }
     
    159159
    160160    if (!child->renderer().isOutOfFlowPositioned()) {
     161        const RenderStyle& childStyle = child->lineStyle();
    161162        if (child->behavesLikeText()) {
    162             RenderStyle* childStyle = child->renderer().style(isFirstLineStyle());
     163            RenderStyle* childStyle = &child->lineStyle();
    163164            if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth())
    164165                child->clearKnownToHaveNoOverflow();
     
    167168            if (box.hasRenderOverflow() || box.hasSelfPaintingLayer())
    168169                child->clearKnownToHaveNoOverflow();
    169         } else if (!child->renderer().isLineBreak() && (child->renderer().style(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
    170                    || (child->renderer().isListMarker() && !toRenderListMarker(child->renderer()).isInside())
    171                    || child->renderer().style(isFirstLineStyle())->hasBorderImageOutsets()))
     170        } else if (!child->renderer().isLineBreak() && (childStyle.boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
     171            || (child->renderer().isListMarker() && !toRenderListMarker(child->renderer()).isInside())
     172            || childStyle.hasBorderImageOutsets()))
    172173            child->clearKnownToHaveNoOverflow();
    173174       
     
    392393            if (rt.textLength()) {
    393394                if (needsWordSpacing && isSpaceOrNewline(rt.characterAt(text->start())))
    394                     logicalLeft += rt.style(isFirstLineStyle())->font().wordSpacing();
     395                    logicalLeft += text->lineStyle().font().wordSpacing();
    395396                needsWordSpacing = !isSpaceOrNewline(rt.characterAt(text->end()));
    396397            }
     
    447448    if (isHorizontal())
    448449        return false;
    449    
    450     if (renderer().style(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
    451         || renderer().style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
     450
     451    const RenderStyle& lineStyle = this->lineStyle();
     452    if (lineStyle.fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
     453        || lineStyle.font().primaryFont()->hasVerticalGlyphs())
    452454        return true;
    453455
     
    460462                return true;
    461463        } else {
    462             if (curr->renderer().style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
     464            if (curr->lineStyle().font().primaryFont()->hasVerticalGlyphs())
    463465                return true;
    464466           
     
    618620    bool isRootBox = isRootInlineBox();
    619621    if (isRootBox) {
    620         const FontMetrics& fontMetrics = renderer().style(isFirstLineStyle())->fontMetrics();
     622        const FontMetrics& fontMetrics = lineStyle().fontMetrics();
    621623        // RootInlineBoxes are always placed on at pixel boundaries in their logical y direction. Not doing
    622624        // so results in incorrect rendering of text decorations, most notably underlines.
     
    659661        LayoutUnit boxHeight = curr->logicalHeight();
    660662        LayoutUnit boxHeightIncludingMargins = boxHeight;
    661            
     663
     664        RenderStyle& childLineStyle = curr->lineStyle();
    662665        if (curr->behavesLikeText() || curr->isInlineFlowBox()) {
    663             const FontMetrics& fontMetrics = curr->renderer().style(isFirstLineStyle())->fontMetrics();
     666            const FontMetrics& fontMetrics = childLineStyle.fontMetrics();
    664667            newLogicalTop += curr->baselinePosition(baselineType) - fontMetrics.ascent(baselineType);
    665668            if (curr->isInlineFlowBox()) {
    666669                RenderBoxModelObject& boxObject = toRenderBoxModelObject(curr->renderer());
    667                 newLogicalTop -= boxObject.style(isFirstLineStyle())->isHorizontalWritingMode()
     670                newLogicalTop -= childLineStyle.isHorizontalWritingMode()
    668671                    ? boxObject.borderTop() + boxObject.paddingTop()
    669672                    : boxObject.borderRight() + boxObject.paddingRight();
     
    701704            if (curr->isInlineTextBox()) {
    702705                TextEmphasisPosition emphasisMarkPosition;
    703                 if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer().style(isFirstLineStyle()), emphasisMarkPosition)) {
     706                if (toInlineTextBox(curr)->getEmphasisMarkPosition(&childLineStyle, emphasisMarkPosition)) {
    704707                    bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver;
    705                     if (emphasisMarkIsOver != curr->renderer().style(isFirstLineStyle())->isFlippedLinesWritingMode())
     708                    if (emphasisMarkIsOver != childLineStyle.isFlippedLinesWritingMode())
    706709                        hasAnnotationsBefore = true;
    707710                    else
     
    789792        return;
    790793
    791     RenderStyle* style = renderer().style(isFirstLineStyle());
    792     if (!style->boxShadow())
     794    const RenderStyle& lineStyle = this->lineStyle();
     795    if (!lineStyle.boxShadow())
    793796        return;
    794797
    795798    LayoutUnit boxShadowLogicalTop;
    796799    LayoutUnit boxShadowLogicalBottom;
    797     style->getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom);
     800    lineStyle.getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom);
    798801   
    799802    // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite shadow that applies, since
    800803    // the line is "upside down" in terms of block coordinates.
    801     LayoutUnit shadowLogicalTop = style->isFlippedLinesWritingMode() ? -boxShadowLogicalBottom : boxShadowLogicalTop;
    802     LayoutUnit shadowLogicalBottom = style->isFlippedLinesWritingMode() ? -boxShadowLogicalTop : boxShadowLogicalBottom;
     804    LayoutUnit shadowLogicalTop = lineStyle.isFlippedLinesWritingMode() ? -boxShadowLogicalBottom : boxShadowLogicalTop;
     805    LayoutUnit shadowLogicalBottom = lineStyle.isFlippedLinesWritingMode() ? -boxShadowLogicalTop : boxShadowLogicalBottom;
    803806   
    804807    LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() + shadowLogicalTop, logicalVisualOverflow.y());
     
    807810    LayoutUnit boxShadowLogicalLeft;
    808811    LayoutUnit boxShadowLogicalRight;
    809     style->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight);
     812    lineStyle.getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight);
    810813
    811814    LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() + boxShadowLogicalLeft, logicalVisualOverflow.x());
     
    822825        return;
    823826   
    824     RenderStyle* style = renderer().style(isFirstLineStyle());
    825     if (!style->hasBorderImageOutsets())
    826         return;
    827 
    828     LayoutBoxExtent borderOutsets = style->borderImageOutsets();
    829 
    830     LayoutUnit borderOutsetLogicalTop = borderOutsets.logicalTop(style->writingMode());
    831     LayoutUnit borderOutsetLogicalBottom = borderOutsets.logicalBottom(style->writingMode());
    832     LayoutUnit borderOutsetLogicalLeft = borderOutsets.logicalLeft(style->writingMode());
    833     LayoutUnit borderOutsetLogicalRight = borderOutsets.logicalRight(style->writingMode());
     827    const RenderStyle& lineStyle = this->lineStyle();
     828    if (!lineStyle.hasBorderImageOutsets())
     829        return;
     830
     831    LayoutBoxExtent borderOutsets = lineStyle.borderImageOutsets();
     832
     833    LayoutUnit borderOutsetLogicalTop = borderOutsets.logicalTop(lineStyle.writingMode());
     834    LayoutUnit borderOutsetLogicalBottom = borderOutsets.logicalBottom(lineStyle.writingMode());
     835    LayoutUnit borderOutsetLogicalLeft = borderOutsets.logicalLeft(lineStyle.writingMode());
     836    LayoutUnit borderOutsetLogicalRight = borderOutsets.logicalRight(lineStyle.writingMode());
    834837
    835838    // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite border that applies, since
    836839    // the line is "upside down" in terms of block coordinates. vertical-rl and horizontal-bt are the flipped line modes.
    837     LayoutUnit outsetLogicalTop = style->isFlippedLinesWritingMode() ? borderOutsetLogicalBottom : borderOutsetLogicalTop;
    838     LayoutUnit outsetLogicalBottom = style->isFlippedLinesWritingMode() ? borderOutsetLogicalTop : borderOutsetLogicalBottom;
     840    LayoutUnit outsetLogicalTop = lineStyle.isFlippedLinesWritingMode() ? borderOutsetLogicalBottom : borderOutsetLogicalTop;
     841    LayoutUnit outsetLogicalBottom = lineStyle.isFlippedLinesWritingMode() ? borderOutsetLogicalTop : borderOutsetLogicalBottom;
    839842
    840843    LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() - outsetLogicalTop, logicalVisualOverflow.y());
     
    856859        return;
    857860
    858     RenderStyle* style = textBox->renderer().style(isFirstLineStyle());
     861    RenderStyle& lineStyle = this->lineStyle();
    859862   
    860863    GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
    861864    GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
    862     bool isFlippedLine = style->isFlippedLinesWritingMode();
     865    bool isFlippedLine = lineStyle.isFlippedLinesWritingMode();
    863866
    864867    int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0;
     
    867870    int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0;
    868871
    869     int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
     872    int strokeOverflow = static_cast<int>(ceilf(lineStyle.textStrokeWidth() / 2.0f));
    870873    int topGlyphOverflow = -strokeOverflow - topGlyphEdge;
    871874    int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge;
     
    874877
    875878    TextEmphasisPosition emphasisMarkPosition;
    876     if (style->textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) {
    877         int emphasisMarkHeight = style->font().emphasisMarkHeight(style->textEmphasisMarkString());
    878         if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!style->isFlippedLinesWritingMode()))
     879    if (lineStyle.textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(&lineStyle, emphasisMarkPosition)) {
     880        int emphasisMarkHeight = lineStyle.font().emphasisMarkHeight(lineStyle.textEmphasisMarkString());
     881        if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!lineStyle.isFlippedLinesWritingMode()))
    879882            topGlyphOverflow = min(topGlyphOverflow, -emphasisMarkHeight);
    880883        else
     
    884887    // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
    885888    // applied to the right, so this is not an issue with left overflow.
    886     rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
     889    rightGlyphOverflow -= min(0, (int)lineStyle.font().letterSpacing());
    887890
    888891    LayoutUnit textShadowLogicalTop;
    889892    LayoutUnit textShadowLogicalBottom;
    890     style->getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom);
     893    lineStyle.getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom);
    891894   
    892895    LayoutUnit childOverflowLogicalTop = min<LayoutUnit>(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow);
     
    895898    LayoutUnit textShadowLogicalLeft;
    896899    LayoutUnit textShadowLogicalRight;
    897     style->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight);
     900    lineStyle.getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight);
    898901   
    899902    LayoutUnit childOverflowLogicalLeft = min<LayoutUnit>(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow);
     
    13071310    LayoutRect localRect(frameRect);
    13081311    flipForWritingMode(localRect);
    1309     LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
    1310    
    1311     GraphicsContext* context = paintInfo.context;
    1312    
     1312
    13131313    // You can use p::first-line to specify a background. If so, the root line boxes for
    13141314    // a line may actually have to paint a background.
    1315     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    1316     if ((!parent() && isFirstLineStyle() && styleToUse != renderer().style()) || (parent() && renderer().hasBoxDecorations())) {
    1317         LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
    1318         // Shadow comes first and is behind the background and border.
    1319         if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
    1320             paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
    1321 
    1322         Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor);
    1323         paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
    1324         paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
    1325 
    1326         // :first-line cannot be used to put borders on a line. Always paint borders with our
    1327         // non-first-line style.
    1328         if (parent() && renderer().style()->hasBorder()) {
    1329             const NinePieceImage& borderImage = renderer().style()->borderImage();
    1330             StyleImage* borderImageSource = borderImage.image();
    1331             bool hasBorderImage = borderImageSource && borderImageSource->canRender(&renderer(), styleToUse->effectiveZoom());
    1332             if (hasBorderImage && !borderImageSource->isLoaded())
    1333                 return; // Don't paint anything while we wait for the image to load.
    1334 
    1335             // The simple case is where we either have no border image or we are the only box for this object.  In those
    1336             // cases only a single call to draw is required.
    1337             if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
    1338                 boxModelObject()->paintBorder(paintInfo, paintRect, renderer().style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
    1339             else {
    1340                 // We have a border image that spans multiple lines.
    1341                 // We need to adjust tx and ty by the width of all previous lines.
    1342                 // Think of border image painting on inlines as though you had one long line, a single continuous
    1343                 // strip.  Even though that strip has been broken up across multiple lines, you still paint it
    1344                 // as though you had one single line.  This means each line has to pick up the image where
    1345                 // the previous line left off.
    1346                 // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
    1347                 // but it isn't even clear how this should work at all.
    1348                 LayoutUnit logicalOffsetOnLine = 0;
    1349                 for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
    1350                     logicalOffsetOnLine += curr->logicalWidth();
    1351                 LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
    1352                 for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
    1353                     totalLogicalWidth += curr->logicalWidth();
    1354                 LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
    1355                 LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
    1356                 LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
    1357                 LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
    1358 
    1359                 LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
    1360                 GraphicsContextStateSaver stateSaver(*context);
    1361                 context->clip(clipRect);
    1362                 boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer().style(isFirstLineStyle()));
    1363             }
    1364         }
     1315    if (parent() && !renderer().hasBoxDecorations())
     1316        return;
     1317    RenderStyle& lineStyle = this->lineStyle();
     1318    if (!parent() && (!isFirstLine() || &lineStyle == renderer().style()))
     1319        return;
     1320
     1321    LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
     1322    GraphicsContext* context = paintInfo.context;
     1323    LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
     1324    // Shadow comes first and is behind the background and border.
     1325    if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
     1326        paintBoxShadow(paintInfo, &lineStyle, Normal, paintRect);
     1327
     1328    Color c = lineStyle.visitedDependentColor(CSSPropertyBackgroundColor);
     1329    paintFillLayers(paintInfo, c, lineStyle.backgroundLayers(), paintRect);
     1330    paintBoxShadow(paintInfo, &lineStyle, Inset, paintRect);
     1331
     1332    // :first-line cannot be used to put borders on a line. Always paint borders with our
     1333    // non-first-line style.
     1334    if (!parent() || !renderer().style()->hasBorder())
     1335        return;
     1336    const NinePieceImage& borderImage = renderer().style()->borderImage();
     1337    StyleImage* borderImageSource = borderImage.image();
     1338    bool hasBorderImage = borderImageSource && borderImageSource->canRender(&renderer(), lineStyle.effectiveZoom());
     1339    if (hasBorderImage && !borderImageSource->isLoaded())
     1340        return; // Don't paint anything while we wait for the image to load.
     1341
     1342    // The simple case is where we either have no border image or we are the only box for this object. In those
     1343    // cases only a single call to draw is required.
     1344    if (!hasBorderImage || (!prevLineBox() && !nextLineBox()))
     1345        boxModelObject()->paintBorder(paintInfo, paintRect, &lineStyle, BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
     1346    else {
     1347        // We have a border image that spans multiple lines.
     1348        // We need to adjust tx and ty by the width of all previous lines.
     1349        // Think of border image painting on inlines as though you had one long line, a single continuous
     1350        // strip. Even though that strip has been broken up across multiple lines, you still paint it
     1351        // as though you had one single line. This means each line has to pick up the image where
     1352        // the previous line left off.
     1353        // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
     1354        // but it isn't even clear how this should work at all.
     1355        LayoutUnit logicalOffsetOnLine = 0;
     1356        for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
     1357            logicalOffsetOnLine += curr->logicalWidth();
     1358        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
     1359        for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
     1360            totalLogicalWidth += curr->logicalWidth();
     1361        LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
     1362        LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
     1363        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
     1364        LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
     1365
     1366        LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
     1367        GraphicsContextStateSaver stateSaver(*context);
     1368        context->clip(clipRect);
     1369        boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), &lineStyle);
    13651370    }
    13661371}
     
    15371542
    15381543        if (curr->isInlineTextBox()) {
    1539             RenderStyle* style = curr->renderer().style(isFirstLineStyle());
     1544            RenderStyle& childLineStyle = curr->lineStyle();
    15401545            TextEmphasisPosition emphasisMarkPosition;
    1541             if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
    1542                 if (!style->isFlippedLinesWritingMode()) {
    1543                     int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
     1546            if (childLineStyle.textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(&childLineStyle, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
     1547                if (!childLineStyle.isFlippedLinesWritingMode()) {
     1548                    int topOfEmphasisMark = curr->logicalTop() - childLineStyle.font().emphasisMarkHeight(childLineStyle.textEmphasisMarkString());
    15441549                    result = max(result, allowedPosition - topOfEmphasisMark);
    15451550                } else {
    1546                     int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
     1551                    int bottomOfEmphasisMark = curr->logicalBottom() + childLineStyle.font().emphasisMarkHeight(childLineStyle.textEmphasisMarkString());
    15471552                    result = max(result, bottomOfEmphasisMark - allowedPosition);
    15481553                }
     
    15851590
    15861591        if (curr->isInlineTextBox()) {
    1587             RenderStyle* style = curr->renderer().style(isFirstLineStyle());
    1588             if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) {
    1589                 if (!style->isFlippedLinesWritingMode()) {
    1590                     LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
     1592            RenderStyle& childLineStyle = curr->lineStyle();
     1593            if (childLineStyle.textEmphasisMark() != TextEmphasisMarkNone && childLineStyle.textEmphasisPosition() == TextEmphasisPositionUnder) {
     1594                if (!childLineStyle.isFlippedLinesWritingMode()) {
     1595                    LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + childLineStyle.font().emphasisMarkHeight(childLineStyle.textEmphasisMarkString());
    15911596                    result = max(result, bottomOfEmphasisMark - allowedPosition);
    15921597                } else {
    1593                     LayoutUnit topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
     1598                    LayoutUnit topOfEmphasisMark = curr->logicalTop() - childLineStyle.font().emphasisMarkHeight(childLineStyle.textEmphasisMarkString());
    15941599                    result = max(result, allowedPosition - topOfEmphasisMark);
    15951600                }
  • trunk/Source/WebCore/rendering/InlineFlowBox.h

    r156092 r156608  
    7474
    7575    RenderBoxModelObject& renderer() const { return toRenderBoxModelObject(InlineBox::renderer()); }
     76    RenderStyle& lineStyle() const { return isFirstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
    7677
    7778    InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
     
    143144        if (!includeLogicalLeftEdge())
    144145            return 0;
    145         return isHorizontal() ? renderer().style(isFirstLineStyle())->borderLeftWidth() : renderer().style(isFirstLineStyle())->borderTopWidth();
     146        return isHorizontal() ? lineStyle().borderLeftWidth() : lineStyle().borderTopWidth();
    146147    }
    147148    int borderLogicalRight() const
     
    149150        if (!includeLogicalRightEdge())
    150151            return 0;
    151         return isHorizontal() ? renderer().style(isFirstLineStyle())->borderRightWidth() : renderer().style(isFirstLineStyle())->borderBottomWidth();
     152        return isHorizontal() ? lineStyle().borderRightWidth() : lineStyle().borderBottomWidth();
    152153    }
    153154    int paddingLogicalLeft() const
  • trunk/Source/WebCore/rendering/InlineTextBox.cpp

    r156500 r156608  
    103103    if (&parent()->renderer() == renderer().parent())
    104104        return parent()->baselinePosition(baselineType);
    105     return toRenderBoxModelObject(renderer().parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
     105    return toRenderBoxModelObject(renderer().parent())->baselinePosition(baselineType, isFirstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
    106106}
    107107
     
    112112    if (&parent()->renderer() == renderer().parent())
    113113        return parent()->lineHeight();
    114     return toRenderBoxModelObject(renderer().parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
     114    return toRenderBoxModelObject(renderer().parent())->lineHeight(isFirstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
    115115}
    116116
     
    212212    LayoutUnit selTop = selectionTop();
    213213    LayoutUnit selHeight = selectionHeight();
    214     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    215     const Font& font = fontToUse(*styleToUse, renderer());
     214    RenderStyle& lineStyle = this->lineStyle();
     215    const Font& font = fontToUse(lineStyle, renderer());
    216216
    217217    BufferForAppendingHyphen charactersWithHyphen;
    218218    bool respectHyphen = ePos == m_len && hasHyphen();
    219     TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0);
     219    TextRun textRun = constructTextRun(&lineStyle, font, respectHyphen ? &charactersWithHyphen : 0);
    220220    if (respectHyphen)
    221221        endPos = textRun.length();
     
    314314        // If we got here that means that we were only partially truncated and we need to return the pixel offset at which
    315315        // to place the ellipsis.
    316         float widthOfVisibleText = renderer().width(m_start, offset, textPos(), isFirstLineStyle());
     316        float widthOfVisibleText = renderer().width(m_start, offset, textPos(), isFirstLine());
    317317
    318318        // The ellipsis needs to be placed just after the last visible character.
     
    393393    // Make sure truncated text is ignored while hittesting.
    394394    if (m_truncation != cNoTruncation) {
    395         LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncation, textPos(), isFirstLineStyle());
     395        LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncation, textPos(), isFirstLine());
    396396
    397397        if (isHorizontal())
     
    556556            // NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the
    557557            // truncated string i.e.  |Hello|CBA| -> |...lo|CBA|
    558             LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncation, textPos(), isFirstLineStyle());
     558            LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncation, textPos(), isFirstLine());
    559559            LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText;
    560560            LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText, 0);
     
    565565    GraphicsContext* context = paintInfo.context;
    566566
    567     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    568    
    569     adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -logicalHeight());
     567    RenderStyle& lineStyle = this->lineStyle();
     568   
     569    adjustedPaintOffset.move(0, lineStyle.isHorizontalWritingMode() ? 0 : -logicalHeight());
    570570
    571571    FloatPoint boxOrigin = locationIncludingFlipping();
     
    573573    FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
    574574
    575     RenderCombineText* combinedText = styleToUse->hasTextCombine() && renderer().isCombineText() && toRenderCombineText(renderer()).isCombined() ? &toRenderCombineText(renderer()) : 0;
     575    RenderCombineText* combinedText = lineStyle.hasTextCombine() && renderer().isCombineText() && toRenderCombineText(renderer()).isCombined() ? &toRenderCombineText(renderer()) : 0;
    576576
    577577    bool shouldRotate = !isHorizontal() && !combinedText;
     
    587587    Color textStrokeColor;
    588588    Color emphasisMarkColor;
    589     float textStrokeWidth = styleToUse->textStrokeWidth();
    590     const ShadowData* textShadow = paintInfo.forceBlackText() ? 0 : styleToUse->textShadow();
     589    float textStrokeWidth = lineStyle.textStrokeWidth();
     590    const ShadowData* textShadow = paintInfo.forceBlackText() ? 0 : lineStyle.textShadow();
    591591
    592592    if (paintInfo.forceBlackText()) {
     
    595595        emphasisMarkColor = Color::black;
    596596    } else {
    597         textFillColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextFillColor);
     597        textFillColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextFillColor);
    598598       
    599599        bool forceBackgroundToWhite = false;
    600600        if (isPrinting) {
    601             if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy)
     601            if (lineStyle.printColorAdjust() == PrintColorAdjustEconomy)
    602602                forceBackgroundToWhite = true;
    603603            if (renderer().frame().settings().shouldPrintBackgrounds())
     
    609609            textFillColor = correctedTextColor(textFillColor, Color::white);
    610610
    611         textStrokeColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
     611        textStrokeColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
    612612       
    613613        // Make the text stroke color legible against a white background
     
    615615            textStrokeColor = correctedTextColor(textStrokeColor, Color::white);
    616616
    617         emphasisMarkColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextEmphasisColor);
     617        emphasisMarkColor = lineStyle.visitedDependentColor(CSSPropertyWebkitTextEmphasisColor);
    618618       
    619619        // Make the text stroke color legible against a white background
     
    671671
    672672    // Set our font.
    673     const Font& font = fontToUse(*styleToUse, renderer());
     673    const Font& font = fontToUse(lineStyle, renderer());
    674674
    675675    FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent());
     
    683683#if PLATFORM(MAC)
    684684        // Custom highlighters go behind everything else.
    685         if (styleToUse->highlight() != nullAtom && !context->paintingDisabled())
    686             paintCustomHighlight(adjustedPaintOffset, styleToUse->highlight());
     685        if (lineStyle.highlight() != nullAtom && !context->paintingDisabled())
     686            paintCustomHighlight(adjustedPaintOffset, lineStyle.highlight());
    687687#endif
    688688
    689689        if (containsComposition && !useCustomUnderlines)
    690             paintCompositionBackground(context, boxOrigin, styleToUse, font,
     690            paintCompositionBackground(context, boxOrigin, &lineStyle, font,
    691691                renderer().frame().editor().compositionStart(),
    692692                renderer().frame().editor().compositionEnd());
    693693
    694         paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
     694        paintDocumentMarkers(context, boxOrigin, &lineStyle, font, true);
    695695
    696696        if (haveSelection && !useCustomUnderlines)
    697             paintSelection(context, boxOrigin, styleToUse, font, selectionFillColor);
     697            paintSelection(context, boxOrigin, &lineStyle, font, selectionFillColor);
    698698    }
    699699
     
    724724
    725725    BufferForAppendingHyphen charactersWithHyphen;
    726     TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength, hasHyphen() ? &charactersWithHyphen : 0);
     726    TextRun textRun = constructTextRun(&lineStyle, font, string, maximumLength, hasHyphen() ? &charactersWithHyphen : 0);
    727727    if (hasHyphen())
    728728        length = textRun.length();
     
    741741    int emphasisMarkOffset = 0;
    742742    TextEmphasisPosition emphasisMarkPosition;
    743     bool hasTextEmphasis = getEmphasisMarkPosition(styleToUse, emphasisMarkPosition);
    744     const AtomicString& emphasisMark = hasTextEmphasis ? styleToUse->textEmphasisMarkString() : nullAtom;
     743    bool hasTextEmphasis = getEmphasisMarkPosition(&lineStyle, emphasisMarkPosition);
     744    const AtomicString& emphasisMark = hasTextEmphasis ? lineStyle.textEmphasisMarkString() : nullAtom;
    745745    if (!emphasisMark.isEmpty())
    746746        emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fontMetrics().descent() + font.emphasisMarkAscent(emphasisMark);
     
    751751        GraphicsContextStateSaver stateSaver(*context, textStrokeWidth > 0);
    752752
    753         updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
     753        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, lineStyle.colorSpace());
    754754        if (!paintSelectedTextSeparately || ePos <= sPos) {
    755755            // FIXME: Truncate right-to-left text correctly.
     
    759759
    760760        if (!emphasisMark.isEmpty()) {
    761             updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
     761            updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth, lineStyle.colorSpace());
    762762
    763763            DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
     
    782782        GraphicsContextStateSaver stateSaver(*context, selectionStrokeWidth > 0);
    783783
    784         updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, styleToUse->colorSpace());
     784        updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, lineStyle.colorSpace());
    785785        paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
    786786        if (!emphasisMark.isEmpty()) {
    787             updateGraphicsContext(context, selectionEmphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
     787            updateGraphicsContext(context, selectionEmphasisMarkColor, textStrokeColor, textStrokeWidth, lineStyle.colorSpace());
    788788
    789789            DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
     
    801801
    802802    // Paint decorations
    803     TextDecoration textDecorations = styleToUse->textDecorationsInEffect();
     803    TextDecoration textDecorations = lineStyle.textDecorationsInEffect();
    804804    if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection) {
    805         updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
     805        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, lineStyle.colorSpace());
    806806        if (combinedText)
    807807            context->concatCTM(rotation(boxRect, Clockwise));
    808         paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDecorationStyle(), textShadow);
     808        paintDecoration(context, boxOrigin, textDecorations, lineStyle.textDecorationStyle(), textShadow);
    809809        if (combinedText)
    810810            context->concatCTM(rotation(boxRect, Counterclockwise));
     
    812812
    813813    if (paintInfo.phase == PaintPhaseForeground) {
    814         paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
     814        paintDocumentMarkers(context, boxOrigin, &lineStyle, font, false);
    815815
    816816        if (useCustomUnderlines) {
     
    11511151    float width = m_logicalWidth;
    11521152    if (m_truncation != cNoTruncation) {
    1153         width = renderer().width(m_start, m_truncation, textPos(), isFirstLineStyle());
     1153        width = renderer().width(m_start, m_truncation, textPos(), isFirstLine());
    11541154        if (!isLeftToRightDirection())
    11551155            localOrigin.move(m_logicalWidth - width, 0);
     
    11591159    Color underline, overline, linethrough;
    11601160    renderer().getTextDecorationColors(deco, underline, overline, linethrough, true);
    1161     if (isFirstLineStyle())
     1161    if (isFirstLine())
    11621162        renderer().getTextDecorationColors(deco, underline, overline, linethrough, true, true);
    11631163   
     
    11681168    bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255);
    11691169
    1170     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    1171     int baseline = styleToUse->fontMetrics().ascent();
     1170    RenderStyle& lineStyle = this->lineStyle();
     1171    int baseline = lineStyle.fontMetrics().ascent();
    11721172
    11731173    bool setClip = false;
     
    12171217            context->setStrokeColor(underline, colorSpace);
    12181218#if ENABLE(CSS3_TEXT)
    1219             TextUnderlinePosition underlinePosition = styleToUse->textUnderlinePosition();
    1220             const int underlineOffset = computeUnderlineOffset(underlinePosition, styleToUse->fontMetrics(), this, textDecorationThickness);
     1219            TextUnderlinePosition underlinePosition = lineStyle.textUnderlinePosition();
     1220            const int underlineOffset = computeUnderlineOffset(underlinePosition, lineStyle.fontMetrics(), this, textDecorationThickness);
    12211221
    12221222            switch (decorationStyle) {
     
    13571357    // we pin to two pixels under the baseline.
    13581358    int lineThickness = cMisspellingLineThickness;
    1359     int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
     1359    int baseline = lineStyle().fontMetrics().ascent();
    13601360    int descent = logicalHeight() - baseline;
    13611361    int underlineOffset;
     
    14911491        paintStart = underline.startOffset;
    14921492        useWholeWidth = false;
    1493         start = renderer().width(m_start, paintStart - m_start, textPos(), isFirstLineStyle());
     1493        start = renderer().width(m_start, paintStart - m_start, textPos(), isFirstLine());
    14941494    }
    14951495    if (paintEnd != underline.endOffset) {      // end points at the last char, not past it
     
    15021502    }
    15031503    if (!useWholeWidth) {
    1504         width = renderer().width(paintStart, paintEnd - paintStart, textPos() + start, isFirstLineStyle());
     1504        width = renderer().width(paintStart, paintEnd - paintStart, textPos() + start, isFirstLine());
    15051505    }
    15061506
     
    15091509    // If there's not enough space the underline will touch or overlap characters.
    15101510    int lineThickness = 1;
    1511     int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
     1511    int baseline = lineStyle().fontMetrics().ascent();
    15121512    if (underline.thick && logicalHeight() - baseline >= 2)
    15131513        lineThickness = 2;
     
    15541554    FontCachePurgePreventer fontCachePurgePreventer;
    15551555
    1556     RenderStyle* style = renderer().style(isFirstLineStyle());
    1557     const Font& font = fontToUse(*style, renderer());
    1558     return font.offsetForPosition(constructTextRun(style, font), lineOffset - logicalLeft(), includePartialGlyphs);
     1556    RenderStyle& lineStyle = this->lineStyle();
     1557    const Font& font = fontToUse(lineStyle, renderer());
     1558    return font.offsetForPosition(constructTextRun(&lineStyle, font), lineOffset - logicalLeft(), includePartialGlyphs);
    15591559}
    15601560
     
    15691569    FontCachePurgePreventer fontCachePurgePreventer;
    15701570
    1571     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    1572     ASSERT(styleToUse);
    1573     const Font& font = fontToUse(*styleToUse, renderer());
     1571    RenderStyle& lineStyle = this->lineStyle();
     1572    const Font& font = fontToUse(lineStyle, renderer());
    15741573    int from = !isLeftToRightDirection() ? offset - m_start : 0;
    15751574    int to = !isLeftToRightDirection() ? m_len : offset - m_start;
    15761575    // FIXME: Do we need to add rightBearing here?
    1577     return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoint(logicalLeft(), 0), 0, from, to).maxX();
     1576    return font.selectionRectForText(constructTextRun(&lineStyle, font), IntPoint(logicalLeft(), 0), 0, from, to).maxX();
    15781577}
    15791578
  • trunk/Source/WebCore/rendering/InlineTextBox.h

    r156094 r156608  
    5959
    6060    RenderText& renderer() const { return toRenderText(InlineBox::renderer()); }
     61    RenderStyle& lineStyle() const { return isFirstLine() ? *renderer().firstLineStyle() : *renderer().style(); }
    6162
    6263    virtual void destroy(RenderArena&) OVERRIDE FINAL;
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r156557 r156608  
    56165616
    56175617    if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
    5618         RenderStyle* s = style(firstLine);
     5618        RenderStyle* s = firstLine ? firstLineStyle() : style();
    56195619        if (s != style())
    56205620            return s->computedLineHeight(&view());
     
    56595659    }
    56605660
    5661     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
     5661    const RenderStyle* style = firstLine ? firstLineStyle() : this->style();
     5662    const FontMetrics& fontMetrics = style->fontMetrics();
    56625663    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
    56635664}
     
    56685669        return replacedHeight;
    56695670
    5670     if (!(style(isFirstLine)->lineBoxContain() & LineBoxContainBlock))
     5671    const RenderStyle* style = isFirstLine ? firstLineStyle() : this->style();
     5672    if (!(style->lineBoxContain() & LineBoxContainBlock))
    56715673        return 0;
    56725674
     
    56815683    if (childrenInline()) {
    56825684        if (firstLineBox())
    5683             return firstLineBox()->logicalTop() + style(true)->fontMetrics().ascent(firstRootBox()->baselineType());
     5685            return firstLineBox()->logicalTop() + firstLineStyle()->fontMetrics().ascent(firstRootBox()->baselineType());
    56845686        else
    56855687            return -1;
     
    57155717                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
    57165718        }
    5717         if (lastLineBox())
    5718             return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->fontMetrics().ascent(lastRootBox()->baselineType());
     5719        if (lastLineBox()) {
     5720            bool isFirstLine = lastLineBox() == firstLineBox();
     5721            RenderStyle* style = isFirstLine ? firstLineStyle() : this->style();
     5722            return lastLineBox()->logicalTop() + style->fontMetrics().ascent(lastRootBox()->baselineType());
     5723        }
    57195724        return -1;
    57205725    } else {
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r156557 r156608  
    382382            ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox());
    383383            parentBox = toInlineFlowBox(newBox);
    384             parentBox->setFirstLineStyleBit(lineInfo.isFirstLine());
     384            parentBox->setIsFirstLine(lineInfo.isFirstLine());
    385385            parentBox->setIsHorizontal(isHorizontalWritingMode());
    386386            if (!hasDefaultLineBoxContain)
     
    623623};
    624624
     625static inline RenderStyle& lineStyle(RenderElement& renderer, const LineInfo& lineInfo)
     626{
     627    return lineInfo.isFirstLine() ? *renderer.firstLineStyle() : *renderer.style();
     628}
     629
    625630static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo,
    626631    GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
     
    628633    HashSet<const SimpleFontData*> fallbackFonts;
    629634    GlyphOverflow glyphOverflow;
    630    
    631     const Font& font = renderer->style(lineInfo.isFirstLine())->font();
     635
     636    const Font& font = lineStyle(*renderer->parent(), lineInfo).font();
    632637    // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
    633638    if (lineBox->fitsToGlyphs()) {
     
    645650   
    646651    LayoutUnit hyphenWidth = 0;
    647     if (toInlineTextBox(run->m_box)->hasHyphen()) {
    648         const Font& font = renderer->style(lineInfo.isFirstLine())->font();
     652    if (toInlineTextBox(run->m_box)->hasHyphen())
    649653        hyphenWidth = measureHyphenWidth(renderer, font, &fallbackFonts);
    650     }
     654
    651655    float measuredWidth = 0;
    652656
     
    913917            if (int length = rt->textLength()) {
    914918                if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
    915                     totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().wordSpacing();
     919                    totalLogicalWidth += lineStyle(*rt->parent(), lineInfo).font().wordSpacing();
    916920                needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1)) && r->m_stop == length;
    917921            }
     
    22152219static bool requiresLineBoxForContent(RenderInline* flow, const LineInfo& lineInfo)
    22162220{
    2217     RenderObject* parent = flow->parent();
    2218     if (flow->document().inNoQuirksMode()
    2219         && (flow->style(lineInfo.isFirstLine())->lineHeight() != parent->style(lineInfo.isFirstLine())->lineHeight()
    2220         || flow->style()->verticalAlign() != parent->style()->verticalAlign()
    2221         || !parent->style()->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flow->style()->font().fontMetrics())))
     2221    RenderElement* parent = flow->parent();
     2222    if (flow->document().inNoQuirksMode()) {
     2223        const RenderStyle& flowStyle = lineStyle(*flow, lineInfo);
     2224        const RenderStyle& parentStyle = lineStyle(*parent, lineInfo);
     2225        if (flowStyle.lineHeight() != parentStyle.lineHeight()
     2226            || flowStyle.verticalAlign() != parentStyle.verticalAlign()
     2227            || !parentStyle.font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flowStyle.font().fontMetrics()))
    22222228        return true;
     2229    }
    22232230    return false;
    22242231}
     
    29062913            }
    29072914
    2908             RenderStyle* style = t->style(lineInfo.isFirstLine());
    2909             const Font& f = style->font();
     2915            RenderStyle& style = lineStyle(*t->parent(), lineInfo);
     2916            const Font& f = style.font();
    29102917            bool isFixedPitch = f.isFixedPitch();
    2911             bool canHyphenate = style->hyphens() == HyphensAuto && WebCore::canHyphenate(style->locale());
     2918            bool canHyphenate = style.hyphens() == HyphensAuto && WebCore::canHyphenate(style.locale());
    29122919
    29132920            unsigned lastSpace = current.m_pos;
     
    29372944                renderTextInfo.m_font = &f;
    29382945                renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
    2939                 renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style->locale());
     2946                renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style.locale());
    29402947            } else if (renderTextInfo.m_layout && renderTextInfo.m_font != &f) {
    29412948                renderTextInfo.m_font = &f;
     
    29482955            // words with their trailing space, then subtract its width.
    29492956            HashSet<const SimpleFontData*> fallbackFonts;
    2950             float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(RenderBlock::constructTextRun(t, f, &space, 1, style), &fallbackFonts) + wordSpacing : 0;
     2957            float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(RenderBlock::constructTextRun(t, f, &space, 1, &style), &fallbackFonts) + wordSpacing : 0;
    29512958
    29522959            UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharacter();
     
    29612968                    lineInfo.setEmpty(false, m_block, &width);
    29622969
    2963                 if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) {
     2970                if (c == softHyphen && autoWrap && !hyphenWidth && style.hyphens() != HyphensNone) {
    29642971                    hyphenWidth = measureHyphenWidth(t, f, &fallbackFonts);
    29652972                    width.addUncommittedWidth(hyphenWidth, *current.m_obj);
     
    29782985
    29792986                bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition, breakNBSP)
    2980                     && (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
     2987                    && (style.hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
    29812988
    29822989                if (betweenWords || midWordBreak) {
     
    30553062                        if (lineWasTooWide || !width.fitsOnLine()) {
    30563063                            if (canHyphenate && !width.fitsOnLine()) {
    3057                                 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);
     3064                                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);
    30583065                                if (m_hyphenated)
    30593066                                    goto end;
     
    30663073                                wordMeasurement.endOffset = lBreak.m_pos;
    30673074                            }
    3068                             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)
     3075                            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)
    30693076                                m_hyphenated = true;
    30703077                            if (lBreak.m_pos && lBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
     
    32073214            if (!width.fitsOnLine()) {
    32083215                if (canHyphenate)
    3209                     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);
    3210 
    3211                 if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style->hyphens() != HyphensNone)
     3216                    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);
     3217
     3218                if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style.hyphens() != HyphensNone)
    32123219                    m_hyphenated = true;
    32133220
  • trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp

    r155689 r156608  
    10091009        DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
    10101010        DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
    1011         const Font& font = style(numVisibleLines == 1)->font();
     1011        const RenderStyle& lineStyle = numVisibleLines == 1 ? *firstLineStyle() : *style();
     1012        const Font& font = lineStyle.font();
    10121013
    10131014        // 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
  • trunk/Source/WebCore/rendering/RenderElement.cpp

    r156527 r156608  
    5454#include "RenderView.h"
    5555#include "SVGRenderSupport.h"
     56#include "StyleResolver.h"
    5657
    5758#if USE(ACCELERATED_COMPOSITING)
     
    176177}
    177178
     179enum StyleCacheState {
     180    Cached,
     181    Uncached
     182};
     183
     184static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheState type, const RenderObject* renderer, RenderStyle* style)
     185{
     186    const RenderObject* rendererForFirstLineStyle = renderer;
     187    if (renderer->isBeforeOrAfterContent())
     188        rendererForFirstLineStyle = renderer->parent();
     189
     190    if (rendererForFirstLineStyle->isRenderBlockFlow() || rendererForFirstLineStyle->isRenderButton()) {
     191        if (RenderBlock* firstLineBlock = rendererForFirstLineStyle->firstLineBlock()) {
     192            if (type == Cached)
     193                return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
     194            return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == renderer ? style : 0);
     195        }
     196    } else if (!rendererForFirstLineStyle->isAnonymous() && rendererForFirstLineStyle->isRenderInline()) {
     197        RenderStyle* parentStyle = rendererForFirstLineStyle->parent()->firstLineStyle();
     198        if (parentStyle != rendererForFirstLineStyle->parent()->style()) {
     199            if (type == Cached) {
     200                // A first-line style is in effect. Cache a first-line style for ourselves.
     201                rendererForFirstLineStyle->style()->setHasPseudoStyle(FIRST_LINE_INHERITED);
     202                return rendererForFirstLineStyle->getCachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle);
     203            }
     204            return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), parentStyle, style);
     205        }
     206    }
     207    return 0;
     208}
     209
     210PassRefPtr<RenderStyle> RenderElement::uncachedFirstLineStyle(RenderStyle* style) const
     211{
     212    if (!document().styleSheetCollection().usesFirstLineRules())
     213        return 0;
     214
     215    return firstLineStyleForCachedUncachedType(Uncached, this, style);
     216}
     217
     218RenderStyle* RenderElement::cachedFirstLineStyle() const
     219{
     220    ASSERT(document().styleSheetCollection().usesFirstLineRules());
     221
     222    RenderStyle* style = this->style();
     223    if (RefPtr<RenderStyle> firstLineStyle = firstLineStyleForCachedUncachedType(Cached, this, style))
     224        return firstLineStyle.get();
     225
     226    return style;
     227}
     228
    178229StyleDifference RenderElement::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
    179230{
  • trunk/Source/WebCore/rendering/RenderElement.h

    r156527 r156608  
    3535
    3636    RenderStyle* style() const { return m_style.get(); }
    37     RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
     37    RenderStyle* firstLineStyle() const;
    3838
    3939    virtual void setStyle(PassRefPtr<RenderStyle>);
     
    7373    RenderElement* rendererForRootBackground();
    7474
     75    // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
     76    // given new style, without accessing the cache.
     77    PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
     78
    7579    // Updates only the local style ptr of the object. Does not update the state of the object,
    7680    // and so only should be called when the style is known not to have changed (or from setStyle).
     
    119123
    120124    StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
     125    RenderStyle* cachedFirstLineStyle() const;
    121126
    122127    RenderObject* m_firstChild;
     
    131136};
    132137
     138inline RenderStyle* RenderElement::firstLineStyle() const
     139{
     140    return document().styleSheetCollection().usesFirstLineRules() ? cachedFirstLineStyle() : style();
     141}
     142
    133143inline LayoutUnit RenderElement::valueForLength(const Length& length, LayoutUnit maximumValue, bool roundPercentages) const
    134144{
     
    176186}
    177187
     188inline RenderStyle* RenderObject::firstLineStyle() const
     189{
     190    if (isText())
     191        return m_parent->firstLineStyle();
     192    return toRenderElement(this)->firstLineStyle();
     193}
     194
    178195inline RenderElement* Element::renderer() const
    179196{
  • trunk/Source/WebCore/rendering/RenderInline.cpp

    r156527 r156608  
    225225    if (!alwaysCreateLineBoxes && checkFonts && document().styleSheetCollection().usesFirstLineRules()) {
    226226        // Have to check the first line style as well.
    227         parentStyle = parent()->style(true);
    228         RenderStyle* childStyle = style(true);
     227        parentStyle = parent()->firstLineStyle();
     228        RenderStyle* childStyle = firstLineStyle();
    229229        alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
    230         || childStyle->verticalAlign() != BASELINE
    231         || parentStyle->lineHeight() != childStyle->lineHeight();
     230            || childStyle->verticalAlign() != BASELINE
     231            || parentStyle->lineHeight() != childStyle->lineHeight();
    232232    }
    233233
     
    571571            if (currBox->inlineBoxWrapper()) {
    572572                const RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root();
    573                 int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
    574                 int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
     573                const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
     574                int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
     575                int logicalHeight = containerStyle.font().fontMetrics().height();
    575576                if (isHorizontal)
    576577                    yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginWidth(), logicalHeight));
     
    586587                for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
    587588                    const RootInlineBox& rootBox = childLine->root();
    588                     int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
    589                     int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
     589                    const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
     590                    int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
     591                    int logicalHeight = containerStyle.fontMetrics().height();
    590592                    if (isHorizontal)
    591593                        yield(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
     
    604606            for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
    605607                const RootInlineBox& rootBox = childText->root();
    606                 int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
    607                 int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
     608                const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
     609                int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
     610                int logicalHeight = containerStyle.font().fontMetrics().height();
    608611                if (isHorizontal)
    609612                    yield(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
     
    615618                // FIXME: This could use a helper to share these with text path.
    616619                const RootInlineBox& rootBox = inlineBox->root();
    617                 int logicalTop = rootBox.logicalTop() + (rootBox.renderer().style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox.isFirstLineStyle())->font().fontMetrics().ascent());
    618                 int logicalHeight = container->style(rootBox.isFirstLineStyle())->font().fontMetrics().height();
     620                const RenderStyle& containerStyle = rootBox.isFirstLine() ? *container->firstLineStyle() : *container->style();
     621                int logicalTop = rootBox.logicalTop() + (rootBox.lineStyle().font().fontMetrics().ascent() - containerStyle.font().fontMetrics().ascent());
     622                int logicalHeight = containerStyle.fontMetrics().height();
    619623                if (isHorizontal)
    620624                    yield(FloatRect(inlineBox->x(), logicalTop, inlineBox->logicalWidth(), logicalHeight));
     
    13531357{
    13541358    if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
    1355         RenderStyle* s = style(firstLine);
    1356         if (s != style())
    1357             return s->computedLineHeight(&view());
     1359        const RenderStyle& firstLineStyle = *this->firstLineStyle();
     1360        if (&firstLineStyle != style())
     1361            return firstLineStyle.computedLineHeight(&view());
    13581362    }
    13591363
     
    13631367int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
    13641368{
    1365     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
     1369    const RenderStyle& style = firstLine ? *firstLineStyle() : *this->style();
     1370    const FontMetrics& fontMetrics = style.fontMetrics();
    13661371    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
    13671372}
  • trunk/Source/WebCore/rendering/RenderLineBreak.cpp

    r156422 r156608  
    5151{
    5252    if (firstLine && document().styleSheetCollection().usesFirstLineRules()) {
    53         RenderStyle* s = style(firstLine);
    54         if (s != style())
    55             return s->computedLineHeight(&view());
     53        const RenderStyle& firstLineStyle = *this->firstLineStyle();
     54        if (&firstLineStyle != style())
     55            return firstLineStyle.computedLineHeight(&view());
    5656    }
    5757
     
    6464int RenderLineBreak::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
    6565{
    66     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
     66    const RenderStyle& style = firstLine ? *firstLineStyle() : *this->style();
     67    const FontMetrics& fontMetrics = style.fontMetrics();
    6768    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
    6869}
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r156527 r156608  
    22332233}
    22342234
    2235 enum StyleCacheState {
    2236     Cached,
    2237     Uncached
    2238 };
    2239 
    2240 static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheState type, const RenderObject* renderer, RenderStyle* style)
    2241 {
    2242     const RenderObject* rendererForFirstLineStyle = renderer;
    2243     if (renderer->isBeforeOrAfterContent())
    2244         rendererForFirstLineStyle = renderer->parent();
    2245 
    2246     if (rendererForFirstLineStyle->isRenderBlockFlow() || rendererForFirstLineStyle->isRenderButton()) {
    2247         if (RenderBlock* firstLineBlock = rendererForFirstLineStyle->firstLineBlock()) {
    2248             if (type == Cached)
    2249                 return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
    2250             return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == renderer ? style : 0);
    2251         }
    2252     } else if (!rendererForFirstLineStyle->isAnonymous() && rendererForFirstLineStyle->isRenderInline()) {
    2253         RenderStyle* parentStyle = rendererForFirstLineStyle->parent()->firstLineStyle();
    2254         if (parentStyle != rendererForFirstLineStyle->parent()->style()) {
    2255             if (type == Cached) {
    2256                 // A first-line style is in effect. Cache a first-line style for ourselves.
    2257                 rendererForFirstLineStyle->style()->setHasPseudoStyle(FIRST_LINE_INHERITED);
    2258                 return rendererForFirstLineStyle->getCachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle);
    2259             }
    2260             return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), parentStyle, style);
    2261         }
    2262     }
    2263     return 0;
    2264 }
    2265 
    2266 PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const
    2267 {
    2268     if (!document().styleSheetCollection().usesFirstLineRules())
    2269         return 0;
    2270 
    2271     ASSERT(!isText());
    2272 
    2273     return firstLineStyleForCachedUncachedType(Uncached, this, style);
    2274 }
    2275 
    2276 RenderStyle* RenderObject::cachedFirstLineStyle() const
    2277 {
    2278     ASSERT(document().styleSheetCollection().usesFirstLineRules());
    2279 
    2280     RenderStyle* style = this->style();
    2281     if (RefPtr<RenderStyle> firstLineStyle = firstLineStyleForCachedUncachedType(Cached, isText() ? parent() : this, style))
    2282         return firstLineStyle.get();
    2283 
    2284     return style;
    2285 }
    2286 
    22872235RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
    22882236{
     
    23552303    Color resultColor;
    23562304    do {
    2357         styleToUse = curr->style(firstlineStyle);
     2305        styleToUse = firstlineStyle ? curr->firstLineStyle() : curr->style();
    23582306        currDecs = styleToUse->textDecoration();
    23592307        resultColor = decorationColor(styleToUse);
     
    23822330    // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
    23832331    if (decorations && curr) {
    2384         styleToUse = curr->style(firstlineStyle);
     2332        styleToUse = firstlineStyle ? curr->firstLineStyle() : curr->style();
    23852333        resultColor = decorationColor(styleToUse);
    23862334        if (decorations & TextDecorationUnderline)
  • trunk/Source/WebCore/rendering/RenderObject.h

    r156527 r156608  
    760760
    761761    RenderStyle* style() const;
    762     RenderStyle* firstLineStyle() const { return document().styleSheetCollection().usesFirstLineRules() ? cachedFirstLineStyle() : style(); }
    763     RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
    764 
    765     // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
    766     // given new style, without accessing the cache.
    767     PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
     762    RenderStyle* firstLineStyle() const;
    768763
    769764    // Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
     
    971966    void removeFromRenderFlowThread();
    972967    void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
    973 
    974     RenderStyle* cachedFirstLineStyle() const;
    975968
    976969    Color selectionColor(int colorProperty) const;
  • trunk/Source/WebCore/rendering/RenderRubyRun.cpp

    r156151 r156608  
    277277}
    278278
     279static bool shouldOverhang(bool firstLine, const RenderObject* renderer, const RenderRubyBase& rubyBase)
     280{
     281    if (!renderer || !renderer->isText())
     282        return false;
     283    const RenderStyle& rubyBaseStyle = firstLine ? *rubyBase.firstLineStyle() : *rubyBase.style();
     284    const RenderStyle& style = firstLine ? *renderer->firstLineStyle() : *renderer->style();
     285    return style.fontSize() <= rubyBaseStyle.fontSize();
     286}
     287
    279288void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const
    280289{
     
    304313    endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang;
    305314
    306     if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
     315    if (!shouldOverhang(firstLine, startRenderer, *rubyBase))
    307316        startOverhang = 0;
    308 
    309     if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
     317    if (!shouldOverhang(firstLine, endRenderer, *rubyBase))
    310318        endOverhang = 0;
    311319
     
    313321    // We can overhang the ruby by no more than half the width of the neighboring text
    314322    // and no more than half the font size.
    315     int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2;
     323    const RenderStyle& rubyTextStyle = firstLine ? *rubyText->firstLineStyle() : *rubyText->style();
     324    int halfWidthOfFontSize = rubyTextStyle.fontSize() / 2;
    316325    if (startOverhang)
    317326        startOverhang = min<int>(startOverhang, min<int>(toRenderText(startRenderer)->minLogicalWidth(), halfWidthOfFontSize));
  • trunk/Source/WebCore/rendering/RenderText.cpp

    r156527 r156608  
    14801480        len = textLength() - from;
    14811481
    1482     return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow);
     1482    const RenderStyle& lineStyle = firstLine ? *firstLineStyle() : *style();
     1483    return width(from, len, lineStyle.font(), xPos, fallbackFonts, glyphOverflow);
    14831484}
    14841485
  • trunk/Source/WebCore/rendering/RenderText.h

    r156527 r156608  
    4848
    4949    RenderStyle* style() const;
    50     RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
     50    RenderStyle* firstLineStyle() const;
    5151
    5252    virtual String originalText() const;
     
    250250}
    251251
     252inline RenderStyle* RenderText::firstLineStyle() const
     253{
     254    return parent()->firstLineStyle();
     255}
     256
    252257#ifdef NDEBUG
    253258inline void RenderText::checkConsistency() const
  • trunk/Source/WebCore/rendering/RootInlineBox.cpp

    r156557 r156608  
    109109int RootInlineBox::baselinePosition(FontBaseline baselineType) const
    110110{
    111     return boxModelObject()->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
     111    return boxModelObject()->baselinePosition(baselineType, isFirstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
    112112}
    113113
    114114LayoutUnit RootInlineBox::lineHeight() const
    115115{
    116     return boxModelObject()->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
     116    return boxModelObject()->lineHeight(isFirstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
    117117}
    118118
     
    212212    paintEllipsisBox(paintInfo, paintOffset, lineTop, lineBottom);
    213213#if PLATFORM(MAC)
    214     RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
    215     if (styleToUse->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
    216         paintCustomHighlight(paintInfo, paintOffset, styleToUse->highlight());
     214    const RenderStyle& lineStyle = this->lineStyle();
     215    if (lineStyle.highlight() != nullAtom && !paintInfo.context->paintingDisabled())
     216        paintCustomHighlight(paintInfo, paintOffset, lineStyle.highlight());
    217217#endif
    218218}
     
    833833    // not to be included.
    834834    if (box->renderer().isReplaced()) {
    835         if (renderer().style(isFirstLineStyle())->lineBoxContain() & LineBoxContainReplaced) {
     835        if (lineStyle().lineBoxContain() & LineBoxContainReplaced) {
    836836            ascent = box->baselinePosition(baselineType());
    837837            descent = box->lineHeight() - ascent;
     
    858858    bool setUsedFontWithLeading = false;
    859859
    860     if (usedFonts && !usedFonts->isEmpty() && (includeFont || (box->renderer().style(isFirstLineStyle())->lineHeight().isNegative() && includeLeading))) {
    861         usedFonts->append(box->renderer().style(isFirstLineStyle())->font().primaryFont());
     860    const RenderStyle& boxLineStyle = box->lineStyle();
     861    if (usedFonts && !usedFonts->isEmpty() && (includeFont || (boxLineStyle.lineHeight().isNegative() && includeLeading))) {
     862        usedFonts->append(boxLineStyle.font().primaryFont());
    862863        for (size_t i = 0; i < usedFonts->size(); ++i) {
    863864            const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics();
     
    897898   
    898899    if (includeFontForBox(box) && !setUsedFont) {
    899         int fontAscent = box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
    900         int fontDescent = box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType());
     900        int fontAscent = boxLineStyle.fontMetrics().ascent(baselineType());
     901        int fontDescent = boxLineStyle.fontMetrics().descent(baselineType());
    901902        setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
    902903        affectsAscent = fontAscent - box->logicalTop() > 0;
     
    908909        affectsAscent = glyphOverflow->top - box->logicalTop() > 0;
    909910        affectsDescent = glyphOverflow->bottom + box->logicalTop() > 0;
    910         glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType())));
    911         glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType())));
     911        glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - boxLineStyle.fontMetrics().ascent(baselineType())));
     912        glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - boxLineStyle.fontMetrics().descent(baselineType())));
    912913    }
    913914
    914915    if (includeMarginForBox(box)) {
    915         LayoutUnit ascentWithMargin = box->renderer().style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
    916         LayoutUnit descentWithMargin = box->renderer().style(isFirstLineStyle())->fontMetrics().descent(baselineType());
     916        LayoutUnit ascentWithMargin = boxLineStyle.fontMetrics().ascent(baselineType());
     917        LayoutUnit descentWithMargin = boxLineStyle.fontMetrics().descent(baselineType());
    917918        if (box->parent() && !box->renderer().isTextOrLineBreak()) {
    918919            ascentWithMargin += box->boxModelObject()->borderAndPaddingBefore() + box->boxModelObject()->marginBefore();
     
    938939
    939940    // This method determines the vertical position for inline elements.
    940     bool firstLine = isFirstLineStyle();
     941    bool firstLine = isFirstLine();
    941942    if (firstLine && !renderer->document().styleSheetCollection().usesFirstLineRules())
    942943        firstLine = false;
     
    955956        return 0;
    956957   
    957     RenderObject* parent = renderer->parent();
     958    RenderElement* parent = renderer->parent();
    958959    if (parent->isRenderInline() && parent->style()->verticalAlign() != TOP && parent->style()->verticalAlign() != BOTTOM)
    959960        verticalPosition = box->parent()->logicalTop();
    960961   
    961962    if (verticalAlign != BASELINE) {
    962         const Font& font = parent->style(firstLine)->font();
     963        const RenderStyle& parentLineStyle = firstLine ? *parent->firstLineStyle() : *parent->style();
     964        const Font& font = parentLineStyle.font();
    963965        const FontMetrics& fontMetrics = font.fontMetrics();
    964966        int fontSize = font.pixelSize();
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r156347 r156608  
    798798    void getBoxShadowHorizontalExtent(LayoutUnit& left, LayoutUnit& right) const { getShadowHorizontalExtent(boxShadow(), left, right); }
    799799    void getBoxShadowVerticalExtent(LayoutUnit& top, LayoutUnit& bottom) const { getShadowVerticalExtent(boxShadow(), top, bottom); }
    800     void getBoxShadowInlineDirectionExtent(LayoutUnit& logicalLeft, LayoutUnit& logicalRight) { getShadowInlineDirectionExtent(boxShadow(), logicalLeft, logicalRight); }
    801     void getBoxShadowBlockDirectionExtent(LayoutUnit& logicalTop, LayoutUnit& logicalBottom) { getShadowBlockDirectionExtent(boxShadow(), logicalTop, logicalBottom); }
     800    void getBoxShadowInlineDirectionExtent(LayoutUnit& logicalLeft, LayoutUnit& logicalRight) const { getShadowInlineDirectionExtent(boxShadow(), logicalLeft, logicalRight); }
     801    void getBoxShadowBlockDirectionExtent(LayoutUnit& logicalTop, LayoutUnit& logicalBottom) const { getShadowBlockDirectionExtent(boxShadow(), logicalTop, logicalBottom); }
    802802
    803803#if ENABLE(CSS_BOX_DECORATION_BREAK)
  • trunk/Source/WebCore/style/StyleResolveTree.cpp

    r156527 r156608  
    546546}
    547547
    548 static bool pseudoStyleCacheIsInvalid(RenderObject* renderer, RenderStyle* newStyle)
     548static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
    549549{
    550550    const RenderStyle* currentStyle = renderer->style();
Note: See TracChangeset for help on using the changeset viewer.