Changeset 25460 in webkit


Ignore:
Timestamp:
Sep 9, 2007 3:54:19 PM (17 years ago)
Author:
zimmermann
Message:

Reviewed by Oliver.

Rework <pattern> support to take overflow & viewBox into account.
Also fix all possible combinations of patternUnits/patternContentUnits, tested by several batik testcases.

Fixes: http://bugs.webkit.org/show_bug.cgi?id=12221 (Webkit ToT fails to render this pattern example)

Location:
branches/feature-branch
Files:
24 added
13 edited

Legend:

Unmodified
Added
Removed
  • branches/feature-branch/LayoutTests/ChangeLog

    r25375 r25460  
     12007-09-09  Nikolas Zimmermann  <zimmermann@kde.org>
     2
     3        Reviewed by Oliver.
     4
     5        Update layout tests results after the <pattern> rework.
     6
     7        * svg/W3C-SVG-1.1/coords-units-01-b-expected.checksum:
     8        * svg/W3C-SVG-1.1/coords-units-01-b-expected.png:
     9        * svg/W3C-SVG-1.1/pservers-grad-06-b-expected.checksum:
     10        * svg/W3C-SVG-1.1/pservers-grad-06-b-expected.png:
     11        * svg/batik/paints/gradientLimit-expected.checksum: Added.
     12        * svg/batik/paints/gradientLimit-expected.png: Added.
     13        * svg/batik/paints/gradientLimit-expected.txt: Added.
     14        * svg/batik/paints/gradientLimit.svg: Added.
     15        * svg/batik/paints/patternPreserveAspectRatioA-expected.checksum: Added.
     16        * svg/batik/paints/patternPreserveAspectRatioA-expected.png: Added.
     17        * svg/batik/paints/patternPreserveAspectRatioA-expected.txt: Added.
     18        * svg/batik/paints/patternPreserveAspectRatioA.svg: Added.
     19        * svg/batik/paints/patternRegionA-expected.checksum: Added.
     20        * svg/batik/paints/patternRegionA-expected.png: Added.
     21        * svg/batik/paints/patternRegionA-expected.txt: Added.
     22        * svg/batik/paints/patternRegionA.svg: Added.
     23        * svg/batik/paints/patternRegionB-expected.checksum: Added.
     24        * svg/batik/paints/patternRegionB-expected.png: Added.
     25        * svg/batik/paints/patternRegionB-expected.txt: Added.
     26        * svg/batik/paints/patternRegions-expected.checksum: Added.
     27        * svg/batik/paints/patternRegions-expected.png: Added.
     28        * svg/batik/paints/patternRegions-expected.txt: Added.
     29        * svg/batik/paints/patternRegions.svg: Added.
     30        * svg/custom/pattern-rotate-expected.checksum:
     31        * svg/custom/pattern-rotate-expected.png:
     32        * svg/custom/stroked-pattern-expected.checksum: Added.
     33        * svg/custom/stroked-pattern-expected.png: Added.
     34        * svg/custom/stroked-pattern-expected.txt: Added.
     35        * svg/custom/stroked-pattern.svg: Added.
     36
    1372007-09-06  Nikolas Zimmermann  <zimmermann@kde.org>
    238
  • branches/feature-branch/LayoutTests/svg/W3C-SVG-1.1/coords-units-01-b-expected.checksum

    r20316 r25460  
    1 1ed93fc6b6256cee24760c5e02df9972
     15b5ada1cf009f12de434052f730b9371
  • branches/feature-branch/LayoutTests/svg/W3C-SVG-1.1/pservers-grad-06-b-expected.checksum

    r21705 r25460  
    1 93184af17cfb48c7962a08d84765b151
     1af804bef148c74265e999f357a10e166
  • branches/feature-branch/LayoutTests/svg/custom/pattern-rotate-expected.checksum

    r25155 r25460  
    1 8d9da3d74119f922ec2dd2d085362b29
     1c1d3a0e2e447a1902c7ac97e7973bcf4
  • branches/feature-branch/WebCore/ChangeLog

    r25372 r25460  
     12007-09-09  Nikolas Zimmermann  <zimmermann@kde.org>
     2
     3        Reviewed by Oliver.
     4
     5        Rework <pattern> support to take overflow & viewBox into account.
     6        Also fix all possible combinations of patternUnits/patternContentUnits, tested by several batik testcases.
     7        (Status: <mask>, <pattern>, <linearGradient>, <radialGradient>, <filter> regions work perfectly. <clipPath> is sill todo)
     8
     9        While I'm at it, add a very helpful debugging tool "dumpCGOutputImage" and rename "dumpOutputImage" to "dumpCIOutputImage".
     10        Also fix possible null image buffer problems. (ie. large alloc)
     11
     12        Fixes: http://bugs.webkit.org/show_bug.cgi?id=12221 (Webkit ToT fails to render this pattern example)
     13
     14        * ksvg2/svg/PatternAttributes.h:
     15        (WebCore::PatternAttributes::PatternAttributes):
     16        (WebCore::PatternAttributes::x):
     17        (WebCore::PatternAttributes::y):
     18        (WebCore::PatternAttributes::width):
     19        (WebCore::PatternAttributes::height):
     20        (WebCore::PatternAttributes::setX):
     21        (WebCore::PatternAttributes::setY):
     22        (WebCore::PatternAttributes::setWidth):
     23        (WebCore::PatternAttributes::setHeight):
     24        * ksvg2/svg/SVGPatternElement.cpp:
     25        (WebCore::SVGPatternElement::buildPattern):
     26        (WebCore::SVGPatternElement::collectPatternProperties):
     27        * platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp:
     28        (WebCore::SVGPaintServerGradient::setup):
     29        * platform/graphics/svg/cg/SVGPaintServerPatternCg.cpp:
     30        (WebCore::patternCallback):
     31        (WebCore::SVGPaintServerPattern::setup):
     32        * platform/graphics/svg/cg/SVGResourceFilterCg.mm:
     33        (WebCore::dumpCIOutputImage):
     34        (WebCore::dumpCGOutputImage):
     35
    1362007-09-05  Nikolas Zimmermann  <zimmermann@kde.org>
    237
  • branches/feature-branch/WebCore/ksvg2/svg/PatternAttributes.h

    r19855 r25460  
    2929    struct PatternAttributes {
    3030        PatternAttributes()
    31             : m_x(0.0)
    32             , m_y(0.0)
    33             , m_width(0.0)
    34             , m_height(0.0)
     31            : m_x()
     32            , m_y()
     33            , m_width()
     34            , m_height()
    3535            , m_boundingBoxMode(true)
    3636            , m_boundingBoxModeContent(false)
     
    4747        }
    4848
    49         double x() const { return m_x; }
    50         double y() const { return m_y; }
    51         double width() const { return m_width; }
    52         double height() const { return m_height; }
     49        SVGLength x() const { return m_x; }
     50        SVGLength y() const { return m_y; }
     51        SVGLength width() const { return m_width; }
     52        SVGLength height() const { return m_height; }
    5353        bool boundingBoxMode() const { return m_boundingBoxMode; }
    5454        bool boundingBoxModeContent() const { return m_boundingBoxModeContent; }
     
    5656        const SVGPatternElement* patternContentElement() const { return m_patternContentElement; }
    5757
    58         void setX(double value) { m_x = value; m_xSet = true; }
    59         void setY(double value) { m_y = value; m_ySet = true; }
    60         void setWidth(double value) { m_width = value; m_widthSet = true; }
    61         void setHeight(double value) { m_height = value; m_heightSet = true; }
     58        void setX(const SVGLength& value) { m_x = value; m_xSet = true; }
     59        void setY(const SVGLength& value) { m_y = value; m_ySet = true; }
     60        void setWidth(const SVGLength& value) { m_width = value; m_widthSet = true; }
     61        void setHeight(const SVGLength& value) { m_height = value; m_heightSet = true; }
    6262        void setBoundingBoxMode(bool value) { m_boundingBoxMode = value; m_boundingBoxModeSet = true; }
    6363        void setBoundingBoxModeContent(bool value) { m_boundingBoxModeContent = value; m_boundingBoxModeContentSet = true; }
     
    7676    private:
    7777        // Properties
    78         double m_x;
    79         double m_y;
    80         double m_width;
    81         double m_height;
     78        SVGLength m_x;
     79        SVGLength m_y;
     80        SVGLength m_width;
     81        SVGLength m_height;
    8282        bool m_boundingBoxMode;
    8383        bool m_boundingBoxModeContent;
  • branches/feature-branch/WebCore/ksvg2/svg/SVGPatternElement.cpp

    r24194 r25460  
    11/*
    2     Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
     2    Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
    33                  2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
    44
     
    3535#include "SVGNames.h"
    3636#include "SVGPaintServerPattern.h"
     37#include "SVGStyledTransformableElement.h"
    3738#include "SVGSVGElement.h"
    3839#include "SVGTransformList.h"
     
    128129
    129130    // If we didn't find any pattern content, ignore the request.
    130     if (!attributes.patternContentElement())
     131    if (!attributes.patternContentElement() || !renderer() || !renderer()->style())
    131132        return;
    132133
     134    FloatRect patternBoundaries;
     135    FloatRect patternContentBoundaries;
     136
    133137    // Determine specified pattern size
    134     float xValue = attributes.x();
    135     float yValue = attributes.y();
    136     float widthValue = attributes.width();
    137     float heightValue = attributes.height();
    138 
    139     if (attributes.boundingBoxMode()) {
    140         xValue *= targetRect.width();
    141         yValue *= targetRect.height();
    142         widthValue *= targetRect.width();
    143         heightValue *= targetRect.height();
    144     }
    145 
    146     // As we're allocating buffers here, clip the buffer size to the target object size as upper boundary
    147     if (widthValue > targetRect.width())
    148         widthValue = targetRect.width();
    149 
    150     if (heightValue > targetRect.height())
    151         heightValue = targetRect.height();
    152 
    153     auto_ptr<ImageBuffer> patternImage = ImageBuffer::create(IntSize(lroundf(widthValue), lroundf(heightValue)), false);
     138    if (attributes.boundingBoxMode())
     139        patternBoundaries = FloatRect(attributes.x().valueAsPercentage() * targetRect.width(),
     140                                      attributes.y().valueAsPercentage() * targetRect.height(),
     141                                      attributes.width().valueAsPercentage() * targetRect.width(),
     142                                      attributes.height().valueAsPercentage() * targetRect.height());
     143    else
     144        patternBoundaries = FloatRect(attributes.x().value(),
     145                                      attributes.y().value(),
     146                                      attributes.width().value(),
     147                                      attributes.height().value());
     148
     149    // Clip pattern boundaries to target boundaries
     150    if (patternBoundaries.width() > targetRect.width())
     151        patternBoundaries.setWidth(targetRect.width());
     152
     153    if (patternBoundaries.height() > targetRect.height())
     154        patternBoundaries.setHeight(targetRect.height());
     155
     156    // Eventually calculate the pattern content boundaries (only needed with overflow="visible").
     157    RenderStyle* style = renderer()->style();
     158    if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) {
     159        for (Node* n = attributes.patternContentElement()->firstChild(); n; n = n->nextSibling()) {
     160            SVGElement* elem = svg_dynamic_cast(n);
     161            if (!elem || !elem->isStyledTransformable())
     162                continue;
     163
     164            SVGStyledElement* e = static_cast<SVGStyledElement*>(elem);
     165            RenderObject* item = e->renderer();
     166            if (!item)
     167                continue;
     168
     169            patternContentBoundaries.unite(item->relativeBBox(true));
     170        }
     171    }
     172
     173    AffineTransform viewBoxCTM = viewBoxToViewTransform(patternBoundaries.width(), patternBoundaries.height());
     174    FloatRect patternBoundariesIncludingOverflow = patternBoundaries;
     175
     176    // Apply objectBoundingBoxMode fixup for patternContentUnits, if viewBox is not set.
     177    if (!patternContentBoundaries.isEmpty()) {
     178        if (!viewBoxCTM.isIdentity())
     179            patternContentBoundaries = viewBoxCTM.mapRect(patternContentBoundaries);
     180        else if (attributes.boundingBoxModeContent())
     181            patternContentBoundaries = FloatRect(patternContentBoundaries.x() * targetRect.width(),
     182                                                 patternContentBoundaries.y() * targetRect.height(),
     183                                                 patternContentBoundaries.width() * targetRect.width(),
     184                                                 patternContentBoundaries.height() * targetRect.height());
     185
     186        patternBoundariesIncludingOverflow.unite(patternContentBoundaries);
     187    }
     188
     189    auto_ptr<ImageBuffer> patternImage = ImageBuffer::create(IntSize(lroundf(patternBoundariesIncludingOverflow.width()),
     190                                                                     lroundf(patternBoundariesIncludingOverflow.height())), false);
     191
    154192    if (!patternImage.get())
    155193        return;
     
    157195    GraphicsContext* context = patternImage->context();
    158196    ASSERT(context);
    159  
    160     if (attributes.boundingBoxModeContent()) {
    161         context->save();
     197
     198    context->save();
     199
     200    // Move to pattern start origin
     201    if (patternBoundariesIncludingOverflow.location() != patternBoundaries.location()) {
     202        context->translate(patternBoundaries.x() - patternBoundariesIncludingOverflow.x(),
     203                           patternBoundaries.y() - patternBoundariesIncludingOverflow.y());
     204
     205        patternBoundaries.setLocation(patternBoundariesIncludingOverflow.location());
     206    }
     207
     208    // Process viewBox or boundingBoxModeContent correction
     209    if (!viewBoxCTM.isIdentity())
     210        context->concatCTM(viewBoxCTM);
     211    else if (attributes.boundingBoxModeContent()) {
     212        context->translate(targetRect.x(), targetRect.y());
    162213        context->scale(FloatSize(targetRect.width(), targetRect.height()));
    163214    }
     
    177228    }
    178229
    179     if (attributes.boundingBoxModeContent())
    180         context->restore();
     230    context->restore();
    181231
    182232    m_resource->setPatternTransform(attributes.patternTransform());
    183     m_resource->setPatternBoundaries(FloatRect(xValue, yValue, widthValue, heightValue));
     233    m_resource->setPatternBoundaries(patternBoundaries);
    184234    m_resource->setTile(patternImage);
    185235}
     
    217267    while (current) {
    218268        if (!attributes.hasX() && current->hasAttribute(SVGNames::xAttr))
    219             attributes.setX(current->x().valueAsPercentage());
     269            attributes.setX(current->x());
    220270
    221271        if (!attributes.hasY() && current->hasAttribute(SVGNames::yAttr))
    222             attributes.setY(current->y().valueAsPercentage());
     272            attributes.setY(current->y());
    223273
    224274        if (!attributes.hasWidth() && current->hasAttribute(SVGNames::widthAttr))
    225             attributes.setWidth(current->width().valueAsPercentage());
     275            attributes.setWidth(current->width());
    226276
    227277        if (!attributes.hasHeight() && current->hasAttribute(SVGNames::heightAttr))
    228             attributes.setHeight(current->height().valueAsPercentage());
     278            attributes.setHeight(current->height());
    229279
    230280        if (!attributes.hasBoundingBoxMode() && current->hasAttribute(SVGNames::patternUnitsAttr))
  • branches/feature-branch/WebCore/platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp

    r25371 r25460  
    287287
    288288        auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(IntSize(maskRect.width(), maskRect.height()), false);
    289         // FIXME: maskImage could be NULL
     289
     290        if (!maskImage.get()) {
     291            context->restore();
     292            return false;
     293        }
    290294
    291295        GraphicsContext* maskImageContext = maskImage->context();
  • branches/feature-branch/WebCore/platform/graphics/svg/cg/SVGPaintServerPatternCg.cpp

    r25155 r25460  
    11/*
    2     Copyright (C) 2006 Nikolas Zimmermann <wildfox@kde.org>
     2    Copyright (C) 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
    33
    44    This file is part of the KDE project
     
    3636{
    3737    ImageBuffer* patternImage = reinterpret_cast<ImageBuffer*>(info);
    38 
    39     IntSize patternContentSize = patternImage->size();
    40     CGContextDrawImage(context, CGRectMake(0, 0, patternContentSize.width(), patternContentSize.height()), patternImage->cgImage());
     38    CGContextDrawImage(context, CGRect(FloatRect(FloatPoint(), patternImage->size())), patternImage->cgImage());
    4139}
    4240
     
    5856        return false;
    5957
    60     CGSize cellSize = CGSize(tile()->size());
    61 
    6258    context->save();
    6359
    6460    // Respect local pattern transformation
    65     CGContextConcatCTM(contextRef, patternTransform());
     61    context->concatCTM(patternTransform());
    6662
    67     // Pattern space seems to start in the lower-left, so we flip the Y here.
    68     CGSize phase = CGSizeMake(patternBoundaries().x(), -patternBoundaries().y());
    69     CGContextSetPatternPhase(contextRef, phase);
     63    // Apply pattern space transformation
     64    context->translate(patternBoundaries().x(), patternBoundaries().y());
     65
     66    // Crude hack to support overflow="visible".
     67    // When the patternBoundaries() size is smaller than the actual tile() size, we run into a problem:
     68    // Our tile contains content which is larger than the pattern cell size. We just draw the pattern
     69    // "out of" cell boundaries, to draw the overflown content, instead of clipping it away. The uppermost
     70    // cell doesn't include the overflown content of the cell right above it though -> that's why we're moving
     71    // down the phase by a very small amount, so we're sure the "cell right above"'s overflown content gets drawn.
     72    CGContextSetPatternPhase(contextRef, CGSizeMake(0.0, -0.01));
    7073
    7174    RenderStyle* style = object->style();
    7275    CGContextSetAlpha(contextRef, style->opacity());
    7376
     77    CGPatternCallbacks callbacks = {0, patternCallback, 0};
     78
    7479    ASSERT(!m_pattern);
    75     CGPatternCallbacks callbacks = {0, patternCallback, NULL};
    7680    m_pattern = CGPatternCreate(tile(),
    77                                 CGRectMake(0, 0, cellSize.width, cellSize.height),
     81                                CGRect(FloatRect(FloatPoint(), tile()->size())),
    7882                                CGContextGetCTM(contextRef),
    7983                                patternBoundaries().width(),
    8084                                patternBoundaries().height(),
    81                                 kCGPatternTilingConstantSpacing, // FIXME: should ask CG guys.
     85                                kCGPatternTilingConstantSpacing,
    8286                                true, // has color
    8387                                &callbacks);
  • branches/feature-branch/WebCore/platform/graphics/svg/cg/SVGResourceFilterCg.mm

    r25176 r25460  
    133133
    134134#ifndef NDEBUG
    135 void dumpOutputImage(CIImage* outputImage, NSString* fileName)
     135// Extremly helpful debugging utilities for any paint server / resource that creates
     136// internal image buffers (ie. gradients on text, masks, filters...)
     137void dumpCIOutputImage(CIImage* outputImage, NSString* fileName)
    136138{
    137139    CGSize extentSize = [outputImage extent].size;
     
    144146
    145147    [imageData writeToFile:fileName atomically:YES];
     148}
     149
     150void dumpCGOutputImage(CGImage* outputImage, NSString* fileName)
     151{
     152    if (CIImage* ciOutputImage = [CIImage imageWithCGImage:outputImage])
     153        dumpCIOutputImage(ciOutputImage, fileName);
    146154}
    147155#endif
Note: See TracChangeset for help on using the changeset viewer.