Changeset 134205 in webkit


Ignore:
Timestamp:
Nov 12, 2012 4:08:15 AM (11 years ago)
Author:
mihnea@adobe.com
Message:

[CSSRegions]Add support for text-shadow in region styling
https://bugs.webkit.org/show_bug.cgi?id=94472

Reviewed by David Hyatt.

Source/WebCore:

Original patch by Andrei Onea.
Add support for text-shadow in region styling (@-webkit-region rule).
In addition to the previously supported region styling properties (background-color and color),
text-shadow requires the computation of an element style in region at layout time.

This patch adds a new method on RenderRegion - ensureRegionStyleForObject - that
can be used to retrieve the object style in region (if already cached) or to compute it
on the spot. When computing the object style in region, we need to compute the style in region
also for the object ancestor, up to the content nodes.

This patch also refactors the way styles in region are computed and stored, because
we can compute the style in region not only at paint time, but also at layout time.

Test: fast/regions/region-style-text-shadow.html

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::isValidRegionStyleProperty):
Allow text-shadow to be used in region styling.

  • rendering/InlineBox.cpp:

(WebCore::InlineBox::styleInRegion):
Retrieve the region style for an InlineBox's renderer, given its RenderRegion.
Compute the style in region if not computed yet.
(WebCore::InlineBox::regionDuringLayout):
Retrieve the region in which an InlineBox is being flowed.

  • rendering/InlineBox.h:
  • rendering/InlineFlowBox.cpp: Take region styling into account.

(WebCore::InlineFlowBox::addToLine):
(WebCore::InlineFlowBox::addTextBoxVisualOverflow):

  • rendering/RenderRegion.cpp:

(WebCore::RenderRegion::setRegionObjectsRegionStyle):
(WebCore::canCacheObjectStyleInRegion):
Test if we can cache the computed style in region.
(WebCore::RenderRegion::restoreRegionObjectsOriginalStyle):
(WebCore::RenderRegion::computeStyleInRegion):
(WebCore::RenderRegion::setChildrenStyleInRegion):
(WebCore::setObjectHasBoxDecorationsFlag):
(WebCore::RenderRegion::setObjectStyleInRegion):
(WebCore::RenderRegion::clearObjectStyleInRegion):
(WebCore::RenderRegion::ensureRegionStyleForObject):

  • rendering/RenderRegion.h:

LayoutTests:

Original patch by Andrei Onea.
Added tests for region styling using the text-shadow property.

  • fast/regions/region-style-text-shadow-expected.html: Added.
  • fast/regions/region-style-text-shadow.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r134199 r134205  
     12012-11-12  Mihnea Ovidenie  <mihnea@adobe.com>
     2
     3        [CSSRegions]Add support for text-shadow in region styling
     4        https://bugs.webkit.org/show_bug.cgi?id=94472
     5
     6        Reviewed by David Hyatt.
     7
     8        Original patch by Andrei Onea.
     9        Added tests for region styling using the text-shadow property.
     10
     11        * fast/regions/region-style-text-shadow-expected.html: Added.
     12        * fast/regions/region-style-text-shadow.html: Added.
     13
    1142012-11-12  Pavel Feldman  <pfeldman@chromium.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r134204 r134205  
     12012-11-12  Mihnea Ovidenie  <mihnea@adobe.com>
     2
     3        [CSSRegions]Add support for text-shadow in region styling
     4        https://bugs.webkit.org/show_bug.cgi?id=94472
     5
     6        Reviewed by David Hyatt.
     7
     8        Original patch by Andrei Onea.
     9        Add support for text-shadow in region styling (@-webkit-region rule).
     10        In addition to the previously supported region styling properties (background-color and color),
     11        text-shadow requires the computation of an element style in region at layout time.
     12
     13        This patch adds a new method on RenderRegion - ensureRegionStyleForObject - that
     14        can be used to retrieve the object style in region (if already cached) or to compute it
     15        on the spot. When computing the object style in region, we need to compute the style in region
     16        also for the object ancestor, up to the content nodes.
     17
     18        This patch also refactors the way styles in region are computed and stored, because
     19        we can compute the style in region not only at paint time, but also at layout time.
     20
     21        Test: fast/regions/region-style-text-shadow.html
     22
     23        * css/StyleResolver.cpp:
     24        (WebCore::StyleResolver::isValidRegionStyleProperty):
     25        Allow text-shadow to be used in region styling.
     26        * rendering/InlineBox.cpp:
     27        (WebCore::InlineBox::styleInRegion):
     28        Retrieve the region style for an InlineBox's renderer, given its RenderRegion.
     29        Compute the style in region if not computed yet.
     30        (WebCore::InlineBox::regionDuringLayout):
     31        Retrieve the region in which an InlineBox is being flowed.
     32        * rendering/InlineBox.h:
     33        * rendering/InlineFlowBox.cpp: Take region styling into account.
     34        (WebCore::InlineFlowBox::addToLine):
     35        (WebCore::InlineFlowBox::addTextBoxVisualOverflow):
     36        * rendering/RenderRegion.cpp:
     37        (WebCore::RenderRegion::setRegionObjectsRegionStyle):
     38        (WebCore::canCacheObjectStyleInRegion):
     39        Test if we can cache the computed style in region.
     40        (WebCore::RenderRegion::restoreRegionObjectsOriginalStyle):
     41        (WebCore::RenderRegion::computeStyleInRegion):
     42        (WebCore::RenderRegion::setChildrenStyleInRegion):
     43        (WebCore::setObjectHasBoxDecorationsFlag):
     44        (WebCore::RenderRegion::setObjectStyleInRegion):
     45        (WebCore::RenderRegion::clearObjectStyleInRegion):
     46        (WebCore::RenderRegion::ensureRegionStyleForObject):
     47        * rendering/RenderRegion.h:
     48
    1492012-11-12  Sheriff Bot  <webkit.review.bot@gmail.com>
    250
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r134190 r134205  
    26812681    case CSSPropertyBackgroundColor:
    26822682    case CSSPropertyColor:
     2683    case CSSPropertyTextShadow:
    26832684        return true;
    26842685    default:
  • trunk/Source/WebCore/rendering/InlineBox.cpp

    r132112 r134205  
    2929#include "RenderArena.h"
    3030#include "RenderBlock.h"
     31#include "RenderFlowThread.h"
     32#include "RenderRegion.h"
     33#include "RenderStyle.h"
     34#include "RenderView.h"
    3135#include "RootInlineBox.h"
    3236
     
    244248}
    245249
     250RenderStyle* InlineBox::styleInRegion(RenderRegion* region) const
     251{
     252    if (!region || !renderer()->inRenderFlowThread())
     253        return renderer()->style(isFirstLineStyle());
     254
     255    // Find the first parent element.
     256    RenderObject* elementRenderer = renderer();
     257    while (elementRenderer && (elementRenderer->isAnonymous() || !elementRenderer->node() || !elementRenderer->node()->isElementNode()))
     258        elementRenderer = elementRenderer->parent();
     259
     260    if (!elementRenderer)
     261        return renderer()->style(isFirstLineStyle());
     262
     263    // FIXME: We should be taking into account isFirstLine
     264    return region->ensureRegionStyleForObject(elementRenderer);
     265}
     266
     267RenderRegion* InlineBox::regionDuringLayout() const
     268{
     269    // This assumes that the box has not been positioned yet
     270    // so it uses the containing block's current logical height to get the region.
     271    ASSERT(renderer() && renderer()->view() && renderer()->view()->layoutState());
     272    if (!renderer()->inRenderFlowThread())
     273        return 0;
     274
     275    RenderFlowThread* flowThread = renderer()->enclosingRenderFlowThread();
     276    ASSERT(flowThread);
     277
     278    RenderBlock* containingBlock = renderer()->containingBlock();
     279    return flowThread->regionAtBlockOffset(containingBlock->offsetFromLogicalTopOfFirstPage() + containingBlock->logicalHeight());
     280}
     281
    246282bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
    247283{
  • trunk/Source/WebCore/rendering/InlineBox.h

    r132112 r134205  
    2929class HitTestRequest;
    3030class HitTestResult;
     31class RenderRegion;
     32class RenderStyle;
    3133class RootInlineBox;
    3234
     
    9799    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
    98100    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
     101
     102    RenderStyle* styleInRegion(RenderRegion*) const;
     103    RenderRegion* regionDuringLayout() const;
    99104
    100105    // Overloaded new operator.
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r133779 r134205  
    124124    if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer()->isOutOfFlowPositioned()) {
    125125        RenderStyle* parentStyle = renderer()->style(isFirstLineStyle());
    126         RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
     126        RenderStyle* childStyle = child->styleInRegion(child->regionDuringLayout());
    127127        bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
    128128        if (child->renderer()->isReplaced())
     
    822822        return;
    823823
    824     RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
     824    RenderStyle* style = textBox->styleInRegion(textBox->regionDuringLayout());
    825825   
    826826    GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
  • trunk/Source/WebCore/rendering/RenderRegion.cpp

    r133779 r134205  
    404404            continue;
    405405
    406         // If the object has style in region, use that instead of computing a new one.
    407         RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
    408         RefPtr<RenderStyle> objectStyleInRegion;
    409         bool objectRegionStyleCached = false;
    410         if (it != m_renderObjectRegionStyle.end()) {
    411             objectStyleInRegion = it->value.style;
    412             ASSERT(it->value.cached);
    413             objectRegionStyleCached = true;
    414         } else
    415             objectStyleInRegion = computeStyleInRegion(object);
    416 
    417         setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCached);
    418 
    419         computeChildrenStyleInRegion(object);
    420     }
    421 }
    422 
     406        setObjectStyleInRegion(object);
     407        setChildrenStyleInRegion(object);
     408    }
     409}
     410
     411static bool canCacheObjectStyleInRegion(const RenderStyle* styleInRegion, const RenderStyle* originalStyle)
     412{
     413    ASSERT(styleInRegion);
     414    ASSERT(originalStyle);
     415
     416    unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
     417    StyleDifference styleDiff = originalStyle->diff(styleInRegion, changedContextSensitiveProperties);
     418    return styleDiff < StyleDifferenceLayoutPositionedMovementOnly;
     419}
     420
     421// Restore the objects original style and cache the style in region for the objects
     422// for which it is safe to cache that style.
    423423void RenderRegion::restoreRegionObjectsOriginalStyle()
    424424{
     
    433433        object->setStyleInternal(objectOriginalStyle);
    434434
    435         bool shouldCacheRegionStyle = iter->value.cached;
    436         if (!shouldCacheRegionStyle) {
    437             // Check whether we should cache the computed style in region.
    438             unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
    439             StyleDifference styleDiff = objectOriginalStyle->diff(objectRegionStyle.get(), changedContextSensitiveProperties);
    440             if (styleDiff < StyleDifferenceLayoutPositionedMovementOnly)
    441                 shouldCacheRegionStyle = true;
    442         }
    443         if (shouldCacheRegionStyle) {
     435        if (iter->value.canBeCached || canCacheObjectStyleInRegion(objectRegionStyle.get(), objectOriginalStyle.get())) {
    444436            ObjectRegionStyleInfo styleInfo;
    445437            styleInfo.style = objectRegionStyle;
    446             styleInfo.cached = true;
     438            styleInfo.canBeCached = true;
     439            styleInfo.originalStyle = false;
    447440            temp.set(object, styleInfo);
    448441        }
     
    466459}
    467460
     461// We also need to compute parent's region style to inherit styling information.
     462// The computation of styles in region should not exceed content nodes boundaries.
    468463PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* object)
    469464{
     
    471466    ASSERT(object->view());
    472467    ASSERT(object->view()->document());
    473     ASSERT(!object->isAnonymous());
     468
     469    if (object->isAnonymous())
     470        return RenderStyle::createAnonymousStyleWithDisplay(ensureRegionStyleForObject(object->parent()), object->style()->display());
     471
     472    if (object->isText())
     473        return RenderStyle::clone(ensureRegionStyleForObject(object->parent()));
     474
     475    // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
    474476    ASSERT(object->node() && object->node()->isElementNode());
    475 
    476     // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
    477477    Element* element = toElement(object->node());
    478     RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document()->styleResolver()->styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
     478    RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document()->styleResolver()->styleForElement(element,
     479        element->inNamedFlow() ? 0 : ensureRegionStyleForObject(object->parent()) /*parent style in region*/, DisallowStyleSharing, MatchAllRules, this);
    479480
    480481    return renderObjectRegionStyle.release();
    481482}
    482483
    483 void RenderRegion::computeChildrenStyleInRegion(const RenderObject* object)
     484void RenderRegion::setChildrenStyleInRegion(const RenderObject* object)
    484485{
    485486    for (RenderObject* child = object->firstChild(); child; child = child->nextSibling()) {
    486 
    487         RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(child);
    488 
    489         RefPtr<RenderStyle> childStyleInRegion;
    490         bool objectRegionStyleCached = false;
    491         if (it != m_renderObjectRegionStyle.end()) {
    492             childStyleInRegion = it->value.style;
    493             objectRegionStyleCached = true;
    494         } else {
    495             if (child->isAnonymous())
    496                 childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(object->style(), child->style()->display());
    497             else if (child->isText())
    498                 childStyleInRegion = RenderStyle::clone(object->style());
    499             else
    500                 childStyleInRegion = computeStyleInRegion(child);
    501         }
    502 
    503         setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCached);
    504 
    505         computeChildrenStyleInRegion(child);
    506     }
    507 }
    508 
    509 void RenderRegion::setObjectStyleInRegion(RenderObject* object, PassRefPtr<RenderStyle> styleInRegion, bool objectRegionStyleCached)
    510 {
     487        setObjectStyleInRegion(child);
     488        setChildrenStyleInRegion(child);
     489    }
     490}
     491
     492static void setObjectHasBoxDecorationsFlag(RenderObject* object)
     493{
     494    ASSERT(object);
    511495    ASSERT(object->inRenderFlowThread());
    512     if (!object->inRenderFlowThread())
    513         return;
    514 
    515     RefPtr<RenderStyle> objectOriginalStyle = object->style();
    516     object->setStyleInternal(styleInRegion);
    517 
    518     if (object->isBoxModelObject() && !object->hasBoxDecorations()) {
    519         bool hasBoxDecorations = object->isTableCell()
     496
     497    if (!object->isBoxModelObject() || object->hasBoxDecorations())
     498        return;
     499
     500    bool hasBoxDecorations = object->isTableCell()
    520501        || object->style()->hasBackground()
    521502        || object->style()->hasBorder()
    522503        || object->style()->hasAppearance()
    523504        || object->style()->boxShadow();
    524         object->setHasBoxDecorations(hasBoxDecorations);
    525     }
    526 
    527     ObjectRegionStyleInfo styleInfo;
    528     styleInfo.style = objectOriginalStyle;
    529     styleInfo.cached = objectRegionStyleCached;
    530     m_renderObjectRegionStyle.set(object, styleInfo);
    531 }
    532 
     505    object->setHasBoxDecorations(hasBoxDecorations);
     506}
     507
     508// Set the current style for the object to be the style in region.
     509// If the style in region is not computed yet, compute it before replacing the original style.
     510// The original object style is stored so that it can be restored later.
     511void RenderRegion::setObjectStyleInRegion(RenderObject* object)
     512{
     513    ASSERT(object->inRenderFlowThread());
     514    ASSERT(!object->isRenderFlowThread());
     515
     516    RefPtr<RenderStyle> objectOriginalStyle = object->style();
     517    RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
     518
     519    if (it == m_renderObjectRegionStyle.end()) {
     520        ensureRegionStyleForObject(object);
     521        it = m_renderObjectRegionStyle.find(object);
     522    }
     523
     524    object->setStyleInternal(it->value.style);
     525    setObjectHasBoxDecorationsFlag(object);
     526
     527    it->value.style = objectOriginalStyle;
     528    it->value.originalStyle = true;
     529}
     530
     531// Clear the style for the children of this object.
    533532void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
    534533{
     
    536535    m_renderObjectRegionStyle.remove(object);
    537536
    538     // Clear the style for the children of this object.
    539537    for (RenderObject* child = object->firstChild(); child; child = child->nextSibling())
    540538        clearObjectStyleInRegion(child);
     539}
     540
     541RenderStyle* RenderRegion::ensureRegionStyleForObject(const RenderObject* object)
     542{
     543    ASSERT(object);
     544    ASSERT(object->inRenderFlowThread());
     545
     546    if (object->isRenderFlowThread())
     547        return object->style();
     548
     549    RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
     550    if (it != m_renderObjectRegionStyle.end()) {
     551        // If the current value stored is the original style, it means that we already
     552        // switched styles and the style in region can be retrived using style().
     553        return it->value.originalStyle ? object->style() : it->value.style.get();
     554    }
     555
     556    RefPtr<RenderStyle> objectStyleInRegion = computeStyleInRegion(object);
     557
     558    ObjectRegionStyleInfo styleInfo;
     559    styleInfo.style = objectStyleInRegion;
     560    styleInfo.originalStyle = false;
     561    styleInfo.canBeCached = canCacheObjectStyleInRegion(objectStyleInRegion.get(), object->style());
     562    m_renderObjectRegionStyle.add(object, styleInfo);
     563
     564    return objectStyleInRegion.get();
    541565}
    542566
  • trunk/Source/WebCore/rendering/RenderRegion.h

    r131348 r134205  
    139139    virtual void repaintFlowThreadContent(const LayoutRect& repaintRect, bool immediate) const;
    140140
     141    RenderStyle* ensureRegionStyleForObject(const RenderObject*);
     142
    141143protected:
    142144    void setRegionObjectsRegionStyle();
     
    162164
    163165    PassRefPtr<RenderStyle> computeStyleInRegion(const RenderObject*);
    164     void computeChildrenStyleInRegion(const RenderObject*);
    165     void setObjectStyleInRegion(RenderObject*, PassRefPtr<RenderStyle>, bool objectRegionStyleCached);
    166     void printRegionObjectsStyles();
     166    void setChildrenStyleInRegion(const RenderObject*);
     167    void setObjectStyleInRegion(RenderObject*);
    167168
    168169    void checkRegionStyle();
     
    193194        // when necessary.
    194195        RefPtr<RenderStyle> style;
    195         // True if the computed style in region is cached.
    196         bool cached;
     196
     197        // True if the computed style in region can be cached.
     198        bool canBeCached : 1;
     199
     200        // True if style keeps the original object style, false if style keeps
     201        // the object style in region.
     202        bool originalStyle : 1;
    197203    };
    198204    typedef HashMap<const RenderObject*, ObjectRegionStyleInfo > RenderObjectRegionStyleMap;
Note: See TracChangeset for help on using the changeset viewer.