Implement the HTML5 canvas tainting rules to prevent potential data leakage
[WebKit-https.git] / WebCore / html / CanvasPattern.cpp
index f0382f781aa6e9df57639439faf92c5c32f54dc7..2cda91783103a484649b9d4cb9cb889b2cfb2d00 100644 (file)
@@ -65,25 +65,39 @@ void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool&
 
 #if PLATFORM(CG)
 
-CanvasPattern::CanvasPattern(CGImageRef image, bool repeatX, bool repeatY)
-    : m_platformImage(image)
+CanvasPattern::CanvasPattern(CGImageRef image, bool repeatX, bool repeatY, bool originClean)
+    : RefCounted<CanvasPattern>(0)
+    , m_platformImage(image)
     , m_cachedImage(0)
     , m_repeatX(repeatX)
     , m_repeatY(repeatY)
+    , m_originClean(originClean)
+{
+}
+
+#elif PLATFORM(CAIRO)
+
+CanvasPattern::CanvasPattern(cairo_surface_t* surface, bool repeatX, bool repeatY, bool originClean)
+    : RefCounted<CanvasPattern>(0)
+    , m_platformImage(cairo_surface_reference(surface))
+    , m_cachedImage(0)
+    , m_repeatX(repeatX)
+    , m_repeatY(repeatY)
+    , m_originClean(originClean)
 {
 }
 
 #endif
 
-CanvasPattern::CanvasPattern(CachedImage* cachedImage, bool repeatX, bool repeatY)
-    :
-#if PLATFORM(CG)
-      m_platformImage(0)
-    ,
+CanvasPattern::CanvasPattern(CachedImage* cachedImage, bool repeatX, bool repeatY, bool originClean)
+    : RefCounted<CanvasPattern>(0)
+#if PLATFORM(CG) || PLATFORM(CAIRO)
+    , m_platformImage(0)
 #endif
-      m_cachedImage(cachedImage)
+    , m_cachedImage(cachedImage)
     , m_repeatX(repeatX)
     , m_repeatY(repeatY)
+    , m_originClean(originClean)
 {
     if (cachedImage)
         cachedImage->ref(this);
@@ -91,8 +105,9 @@ CanvasPattern::CanvasPattern(CachedImage* cachedImage, bool repeatX, bool repeat
 
 CanvasPattern::~CanvasPattern()
 {
-#if PLATFORM(CG)
-    CGImageRelease(m_platformImage);
+#if PLATFORM(CAIRO)
+    if (m_platformImage)
+        cairo_surface_destroy(m_platformImage);
 #endif
     if (m_cachedImage)
         m_cachedImage->deref(this);
@@ -121,6 +136,10 @@ static void patternCallback(void* info, CGContextRef context)
 
     if (image->getCGImageRef()) {
         CGContextDrawImage(context, rect, image->getCGImageRef());
+        // FIXME: We should refactor this code to use the platform-independent 
+        // drawing API in all cases. Then, this didDraw call will happen 
+        // automatically, and we can remove it.
+        cachedImage->didDraw(image);
         return;
     }
 
@@ -138,8 +157,8 @@ CGPatternRef CanvasPattern::createPattern(const CGAffineTransform& transform)
     rect.origin.x = 0;
     rect.origin.y = 0;
     if (m_platformImage) {
-        rect.size.width = CGImageGetWidth(m_platformImage);
-        rect.size.height = CGImageGetHeight(m_platformImage);
+        rect.size.width = CGImageGetWidth(m_platformImage.get());
+        rect.size.height = CGImageGetHeight(m_platformImage.get());
     } else {
         if (!m_cachedImage)
             return 0;
@@ -159,7 +178,7 @@ CGPatternRef CanvasPattern::createPattern(const CGAffineTransform& transform)
     // INT_MAX is almost correct, but there seems to be some number wrapping occuring making the fill
     // pattern is not filled correctly. 
     // So, just pick a really large number that works. 
-    float yStep = m_repeatY ? rect.size.height : (100000000.0);
+    float yStep = m_repeatY ? rect.size.height : (100000000.0f);
 
     const CGPatternCallbacks patternCallbacks = { 0, patternCallback, patternReleaseCallback };
     ref();
@@ -167,6 +186,32 @@ CGPatternRef CanvasPattern::createPattern(const CGAffineTransform& transform)
         kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks);
 }
 
+#elif PLATFORM(CAIRO)
+
+cairo_pattern_t* CanvasPattern::createPattern(const cairo_matrix_t& m)
+{
+    cairo_surface_t* surface = 0;
+    if (m_platformImage) {
+        surface = m_platformImage;
+    } else {
+        if (!m_cachedImage)
+            return 0;
+        Image* image = m_cachedImage->image();
+        if (!image)
+            return 0;
+        surface = image->nativeImageForCurrentFrame();
+    }
+
+    if (!surface)
+        return 0;
+
+    cairo_pattern_t* pattern = cairo_pattern_create_for_surface(surface);
+    cairo_pattern_set_matrix(pattern, &m);
+    if (m_repeatX || m_repeatY)
+        cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
+    return pattern;
+}
+
 #endif
 
 }