Changeset 91125 in webkit


Ignore:
Timestamp:
Jul 15, 2011 4:00:16 PM (13 years ago)
Author:
rwlbuis@webkit.org
Message:

2011-07-15 Rob Buis <rbuis@rim.com>

Stroking of zero-length paths in SVG should change according to erratum
https://bugs.webkit.org/show_bug.cgi?id=18356

Reviewed by Nikolas Zimmermann.

Ensure rendering of zero-length paths with stroke-linecap=square works by
creating the square rectangle manually.

Tests: svg/W3C-SVG-1.1-SE/painting-control-04-f.svg

svg/custom/zero-path-square-cap-rendering.svg

  • platform/graphics/GraphicsContext.h: (WebCore::GraphicsContextStateSaver::context):
  • rendering/svg/RenderSVGPath.cpp: (WebCore::RenderSVGPath::strokeContains): (WebCore::RenderSVGPath::shouldStrokeZeroLengthSubpath): (WebCore::RenderSVGPath::zeroLengthSubpathRect): (WebCore::RenderSVGPath::setupSquareCapPath): (WebCore::RenderSVGPath::setupNonScalingStrokePath): (WebCore::RenderSVGPath::fillAndStrokePath): (WebCore::RenderSVGPath::updateCachedBoundaries):
  • rendering/svg/RenderSVGPath.h:
Location:
trunk
Files:
6 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r91122 r91125  
     12011-07-15  Rob Buis  <rbuis@rim.com>
     2
     3        Stroking of zero-length paths in SVG should change according to erratum
     4        https://bugs.webkit.org/show_bug.cgi?id=18356
     5
     6        Reviewed by Nikolas Zimmermann.
     7
     8        * platform/mac/svg/W3C-SVG-1.1-SE/painting-control-04-f-expected.png: Added.
     9        * platform/mac/svg/W3C-SVG-1.1-SE/painting-control-04-f-expected.txt: Added.
     10        * platform/mac/svg/custom/zero-path-square-cap-rendering-expected.png: Added.
     11        * platform/mac/svg/custom/zero-path-square-cap-rendering-expected.txt: Added.
     12        * svg/W3C-SVG-1.1-SE/painting-control-04-f.svg: Added.
     13        * svg/custom/zero-path-square-cap-rendering.svg: Added.
     14
    1152011-07-15  Tony Chang  <tony@chromium.org>
    216
  • trunk/Source/WebCore/ChangeLog

    r91114 r91125  
     12011-07-15  Rob Buis  <rbuis@rim.com>
     2
     3        Stroking of zero-length paths in SVG should change according to erratum
     4        https://bugs.webkit.org/show_bug.cgi?id=18356
     5
     6        Reviewed by Nikolas Zimmermann.
     7
     8        Ensure rendering of zero-length paths with stroke-linecap=square works by
     9        creating the square rectangle manually.
     10
     11        Tests: svg/W3C-SVG-1.1-SE/painting-control-04-f.svg
     12               svg/custom/zero-path-square-cap-rendering.svg
     13
     14        * platform/graphics/GraphicsContext.h:
     15        (WebCore::GraphicsContextStateSaver::context):
     16        * rendering/svg/RenderSVGPath.cpp:
     17        (WebCore::RenderSVGPath::strokeContains):
     18        (WebCore::RenderSVGPath::shouldStrokeZeroLengthSubpath):
     19        (WebCore::RenderSVGPath::zeroLengthSubpathRect):
     20        (WebCore::RenderSVGPath::setupSquareCapPath):
     21        (WebCore::RenderSVGPath::setupNonScalingStrokePath):
     22        (WebCore::RenderSVGPath::fillAndStrokePath):
     23        (WebCore::RenderSVGPath::updateCachedBoundaries):
     24        * rendering/svg/RenderSVGPath.h:
     25
    1262011-06-27  Adrienne Walker  <enne@google.com>
    227
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.h

    r90919 r91125  
    581581        }
    582582       
     583        GraphicsContext* const context() const { return &m_context; }
     584
    583585    private:
    584586        GraphicsContext& m_context;
  • trunk/Source/WebCore/rendering/svg/RenderSVGPath.cpp

    r90698 r91125  
    100100        return false;
    101101
     102    if (shouldStrokeZeroLengthSubpath())
     103        return zeroLengthSubpathRect().contains(point);
     104
    102105    BoundingRectStrokeStyleApplier strokeStyle(this, style());
    103106    return m_path.strokeContains(&strokeStyle, point);
     
    147150    repainter.repaintAfterLayout();
    148151    setNeedsLayout(false);
     152}
     153
     154bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
     155{
     156    // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
     157    // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
     158    return style()->svgStyle()->capStyle() == SquareCap && !m_fillBoundingBox.width() && !m_fillBoundingBox.height();
     159}
     160
     161FloatRect RenderSVGPath::zeroLengthSubpathRect() const
     162{
     163    SVGElement* svgElement = static_cast<SVGElement*>(node());
     164    float strokeWidth = style()->svgStyle()->strokeWidth().value(svgElement);
     165    return FloatRect(m_fillBoundingBox.x() - strokeWidth / 2., m_fillBoundingBox.y() - strokeWidth / 2., strokeWidth, strokeWidth);
     166}
     167
     168void RenderSVGPath::setupSquareCapPath(Path*& usePath, int& applyMode)
     169{
     170    // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
     171    // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
     172    DEFINE_STATIC_LOCAL(Path, tempPath, ());
     173
     174    applyMode = ApplyToFillMode;
     175    usePath = &tempPath;
     176    usePath->clear();
     177    usePath->addRect(zeroLengthSubpathRect());
     178}
     179
     180bool RenderSVGPath::setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver& stateSaver)
     181{
     182    DEFINE_STATIC_LOCAL(Path, tempPath, ());
     183
     184    SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
     185    AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
     186    if (!nonScalingStrokeTransform.isInvertible())
     187        return false;
     188
     189    tempPath = m_path;
     190    usePath = &tempPath;
     191    tempPath.transform(nonScalingStrokeTransform);
     192
     193    stateSaver.save();
     194    stateSaver.context()->concatCTM(nonScalingStrokeTransform.inverse());
     195    return true;
    149196}
    150197
     
    170217        return;
    171218
    172     Path path;
     219    Path* usePath = &m_path;
     220    int applyMode = ApplyToStrokeMode;
    173221
    174222    bool nonScalingStroke = style->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE;
    175223
    176224    GraphicsContextStateSaver stateSaver(*context, false);
    177     if (nonScalingStroke) {
    178         SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
    179         AffineTransform nonScalingStrokeTransform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
    180         if (!nonScalingStrokeTransform.isInvertible())
    181             return;
    182 
    183         path = m_path;
    184         path.transform(nonScalingStrokeTransform);
    185 
    186         stateSaver.save();
    187         context->concatCTM(nonScalingStrokeTransform.inverse());
    188     }
    189 
    190     if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode))
    191         strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path);
     225
     226    // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
     227    // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
     228    // FIXME: this does not work for zero-length subpaths, only when total path is zero-length
     229    if (shouldStrokeZeroLengthSubpath())
     230        setupSquareCapPath(usePath, applyMode);
     231    else if (nonScalingStroke) {
     232       if (!setupNonScalingStrokePath(usePath, stateSaver))
     233           return;
     234    }
     235
     236    if (strokePaintingResource->applyResource(this, style, context, applyMode))
     237        strokePaintingResource->postApplyResource(this, context, applyMode, usePath);
    192238    else if (fallbackColor.isValid()) {
    193239        RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
    194240        fallbackResource->setColor(fallbackColor);
    195         if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode))
    196             fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, nonScalingStroke ? &path : &m_path);
     241        if (fallbackResource->applyResource(this, style, context, applyMode))
     242            fallbackResource->postApplyResource(this, context, applyMode, usePath);
    197243    }
    198244}
     
    310356    m_fillBoundingBox = m_path.boundingRect();
    311357
     358    // Spec(11.4): Any zero length subpath shall not be stroked if the ‘stroke-linecap’ property has a value of butt
     359    // but shall be stroked if the ‘stroke-linecap’ property has a value of round or square
     360    if (shouldStrokeZeroLengthSubpath()) {
     361        m_strokeAndMarkerBoundingBox = zeroLengthSubpathRect();
     362        // Cache smallest possible repaint rectangle
     363        m_repaintBoundingBox = m_strokeAndMarkerBoundingBox;
     364        SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
     365        return;
     366    }
     367
    312368    // Cache _unclipped_ stroke bounding box, used for calculations in resources (includes marker boundaries)
    313369    m_strokeAndMarkerBoundingBox = m_fillBoundingBox;
  • trunk/Source/WebCore/rendering/svg/RenderSVGPath.h

    r90590 r91125  
    3434
    3535class FloatPoint;
     36class GraphicsContextStateSaver;
    3637class RenderSVGContainer;
    3738class SVGStyledTransformableElement;
     
    6869    FloatRect calculateMarkerBoundsIfNeeded();
    6970    void updateCachedBoundaries();
     71
     72    void setupSquareCapPath(Path*& usePath, int& applyMode);
     73    bool setupNonScalingStrokePath(Path*& usePath, GraphicsContextStateSaver&);
     74    bool shouldStrokeZeroLengthSubpath() const;
     75    FloatRect zeroLengthSubpathRect() const;
    7076
    7177private:
Note: See TracChangeset for help on using the changeset viewer.