Changeset 27781 in webkit


Ignore:
Timestamp:
Nov 13, 2007 7:48:44 PM (16 years ago)
Author:
oliver@apple.com
Message:

Fix <rdar://problem/5365030> calling dataWithPDFInsideRect on an SVG with a gradient crashes (14780)

Reviewed by Anders.

When drawing directly to PDF CG may delay the use of the gradient function until outside our
standard drawing path, which in turn could let us invalidate the caches before they were used.

To work around this we now store the cached stops in a RefCounted object, so that we can ensure
that cache exists as long as required.

Location:
trunk/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r27779 r27781  
     12007-11-13  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Anders.
     4
     5        <rdar://problem/5365030> calling dataWithPDFInsideRect on an SVG with a gradient crashes (14780)
     6
     7        When drawing directly to PDF CG may delay the use of the gradient function until outside our
     8        standard drawing path, which in turn could let us invalidate the caches before they were used.
     9
     10        To work around this we now store the cached stops in a RefCounted object, so that we can ensure
     11        that cache exists as long as required.
     12       
     13        * platform/graphics/svg/SVGPaintServerGradient.cpp:
     14        (WebCore::SVGPaintServerGradient::SVGPaintServerGradient):
     15        * platform/graphics/svg/SVGPaintServerGradient.h:
     16        * platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp:
     17        (WebCore::cgGradientCallback):
     18        (WebCore::CGShadingRefForLinearGradient):
     19        (WebCore::CGShadingRefForRadialGradient):
     20        (WebCore::SVGPaintServerGradient::updateQuartzGradientStopsCache):
     21
    1222007-11-13  Anders Carlsson  <andersca@apple.com>
    223
  • trunk/WebCore/platform/graphics/svg/SVGPaintServerGradient.cpp

    r19855 r27781  
    6767#if PLATFORM(CG)
    6868    , m_stopsCache(0)
    69     , m_stopsCount(0)
    7069    , m_shadingCache(0)
    7170    , m_savedContext(0)
     
    7978{
    8079#if PLATFORM(CG)
    81     delete m_stopsCache;
    8280    CGShadingRelease(m_shadingCache);
    8381#endif
  • trunk/WebCore/platform/graphics/svg/SVGPaintServerGradient.h

    r26446 r27781  
    3232#include "Color.h"
    3333#include "SVGPaintServer.h"
     34
     35#include <wtf/RefCounted.h>
     36#include <wtf/RefPtr.h>
    3437
    3538#if PLATFORM(QT)
     
    111114            CGFloat previousDeltaInverse;
    112115        } QuartzGradientStop;
     116       
     117        struct SharedStopCache : public RefCounted<SharedStopCache> {
     118            Vector<QuartzGradientStop> m_stops;
     119        };
    113120
    114         QuartzGradientStop* m_stopsCache;
    115         int m_stopsCount;
     121        RefPtr<SharedStopCache> m_stopsCache;
    116122
    117123        CGShadingRef m_shadingCache;
  • trunk/WebCore/platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp

    r26749 r27781  
    4141namespace WebCore {
    4242
     43static void releaseCachedStops(void* info)
     44{
     45    reinterpret_cast<SVGPaintServerGradient::SharedStopCache*>(info)->deref();
     46}
     47
    4348static void cgGradientCallback(void* info, const CGFloat* inValues, CGFloat* outColor)
    4449{
    45     const SVGPaintServerGradient* server = reinterpret_cast<const SVGPaintServerGradient*>(info);
    46     SVGPaintServerGradient::QuartzGradientStop* stops = server->m_stopsCache;
    47     int stopsCount = server->m_stopsCount;
     50    SVGPaintServerGradient::SharedStopCache* stopsCache = reinterpret_cast<SVGPaintServerGradient::SharedStopCache*>(info);
     51   
     52    SVGPaintServerGradient::QuartzGradientStop* stops = stopsCache->m_stops.data();
     53       
     54    int stopsCount = stopsCache->m_stops.size();
    4855
    4956    CGFloat inValue = inValues[0];
     
    8794    CGPoint end = CGPoint(server->gradientEnd());
    8895
    89     CGFunctionCallbacks callbacks = {0, cgGradientCallback, NULL};
     96    CGFunctionCallbacks callbacks = {0, cgGradientCallback, releaseCachedStops};
    9097    CGFloat domainLimits[2] = {0, 1};
    9198    CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1};
    92     CGFunctionRef shadingFunction = CGFunctionCreate((void *)server, 1, domainLimits, 4, rangeLimits, &callbacks);
     99    server->m_stopsCache->ref();
     100    CGFunctionRef shadingFunction = CGFunctionCreate(server->m_stopsCache.get(), 1, domainLimits, 4, rangeLimits, &callbacks);
    93101
    94102    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
     
    116124    }
    117125
    118     CGFunctionCallbacks callbacks = {0, cgGradientCallback, NULL};
     126    CGFunctionCallbacks callbacks = {0, cgGradientCallback, releaseCachedStops};
    119127    CGFloat domainLimits[2] = {0, 1};
    120128    CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1};
    121     CGFunctionRef shadingFunction = CGFunctionCreate((void *)server, 1, domainLimits, 4, rangeLimits, &callbacks);
     129    server->m_stopsCache->ref();
     130    CGFunctionRef shadingFunction = CGFunctionCreate(server->m_stopsCache.get(), 1, domainLimits, 4, rangeLimits, &callbacks);
    122131
    123132    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
     
    130139void SVGPaintServerGradient::updateQuartzGradientStopsCache(const Vector<SVGGradientStop>& stops)
    131140{
    132     delete m_stopsCache;
    133 
    134     m_stopsCount = stops.size();
    135     m_stopsCache = new SVGPaintServerGradient::QuartzGradientStop[m_stopsCount];
    136 
     141    m_stopsCache = new SharedStopCache;
     142    Vector<QuartzGradientStop>& stopsCache = m_stopsCache->m_stops;
     143    stopsCache.resize(stops.size());
    137144    CGFloat previousOffset = 0.0f;
    138145    for (unsigned i = 0; i < stops.size(); ++i) {
    139146        CGFloat currOffset = min(max(stops[i].first, previousOffset), static_cast<CGFloat>(1.0));
    140         m_stopsCache[i].offset = currOffset;
    141         m_stopsCache[i].previousDeltaInverse = 1.0f / (currOffset - previousOffset);
     147        stopsCache[i].offset = currOffset;
     148        stopsCache[i].previousDeltaInverse = 1.0f / (currOffset - previousOffset);
    142149        previousOffset = currOffset;
    143         CGFloat* ca = m_stopsCache[i].colorArray;
     150        CGFloat* ca = stopsCache[i].colorArray;
    144151        stops[i].second.getRGBA(ca[0], ca[1], ca[2], ca[3]);
    145152    }
     
    322329{
    323330    // Invalidate caches
    324     delete m_stopsCache;
    325331    CGShadingRelease(m_shadingCache);
    326332
Note: See TracChangeset for help on using the changeset viewer.