Cache image properties and frame durations.
authorrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Nov 2004 19:16:30 +0000 (19:16 +0000)
committerrjw <rjw@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Nov 2004 19:16:30 +0000 (19:16 +0000)
Create NSImage and TIFF representations from CGImage, lazily, as needed for
dragging and element info dictionary.

        Reviewed by John.

        * WebCoreSupport.subproj/WebImageData.h:
        * WebCoreSupport.subproj/WebImageData.m:
        (-[WebImageData dealloc]):
        (-[WebImageData size]):
        (-[WebImageData propertiesAtIndex:]):
        (-[WebImageData _frameDurationAt:]):
        (-[WebImageData _frameDuration]):
        * WebCoreSupport.subproj/WebImageRenderer.h:
        * WebCoreSupport.subproj/WebImageRenderer.m:
        (-[WebImageRenderer dealloc]):
        (-[WebImageRenderer TIFFRepresentation]):
        (-[WebImageRenderer image]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8006 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/WebCoreSupport.subproj/WebImageData.h
WebKit/WebCoreSupport.subproj/WebImageData.m
WebKit/WebCoreSupport.subproj/WebImageRenderer.h
WebKit/WebCoreSupport.subproj/WebImageRenderer.m

index 7a057025283cafa3088041a2c873e435b89adf2d..a789643d3e6ea8586627b105d6000abd6aa92012 100644 (file)
@@ -1,3 +1,24 @@
+2004-11-15  Richard Williamson   <rjw@apple.com>
+
+       Cache image properties and frame durations.
+       Create NSImage and TIFF representations from CGImage, lazily, as needed for
+       dragging and element info dictionary.
+
+        Reviewed by John.
+
+        * WebCoreSupport.subproj/WebImageData.h:
+        * WebCoreSupport.subproj/WebImageData.m:
+        (-[WebImageData dealloc]):
+        (-[WebImageData size]):
+        (-[WebImageData propertiesAtIndex:]):
+        (-[WebImageData _frameDurationAt:]):
+        (-[WebImageData _frameDuration]):
+        * WebCoreSupport.subproj/WebImageRenderer.h:
+        * WebCoreSupport.subproj/WebImageRenderer.m:
+        (-[WebImageRenderer dealloc]):
+        (-[WebImageRenderer TIFFRepresentation]):
+        (-[WebImageRenderer image]):
+
 2004-11-14  Maciej Stachowiak  <mjs@apple.com>
 
         Reviewed by John.
index eea4de63e8e3462909b1c6347d49f5bb6f6b4720..77013c635a11ffae01924f791625d637b9edb435 100644 (file)
     CGImageRef *images;
     CGImageSourceRef imageSource;
 
+    CGSize size;
+    BOOL haveSize;
+    
     CFMutableDictionaryRef animatingRenderers;
     NSTimer *frameTimer;
     float *frameDurations;
+    
+    CFDictionaryRef *imageProperties;
+
     size_t currentFrame;
     int repetitionsComplete;
     BOOL animationFinished;
@@ -36,6 +42,7 @@
 - (void)removeAnimatingRenderer:(WebImageRenderer *)self;
 - (BOOL)isAnimationFinished;
 - (size_t)currentFrame;
+- (CFDictionaryRef)propertiesAtIndex:(size_t)index;
 
 @end
 
index defd76ae9be69a1305607f6007559b8c392b8e5f..76f31d8fbca2c140d336421709e49e28cf597613 100644 (file)
@@ -45,8 +45,18 @@ static CFDictionaryRef imageSourceOptions;
 
 - (void)dealloc
 {
-    [self _commonTermination];
+    size_t i, num;
+    
+    num = [self numberOfImages];
+    for (i = 0; i < num; i++) {
+        CFRelease (imageProperties[i]);
+    }
+    free (imageProperties);
+    
+    free (frameDurations);
 
+    [self _commonTermination];
+    
     [super dealloc];
 }
 
@@ -290,73 +300,104 @@ CGPatternCallbacks patternCallbacks = { 0, drawPattern, NULL };
     float w = 0.f, h = 0.f;
 
     if (!haveSize) {
-       CFDictionaryRef properties = CGImageSourceGetPropertiesAtIndex (imageSource, 0, 0);
-       if (properties) {
-           CFNumberRef num = CFDictionaryGetValue (properties, kCGImagePropertyPixelWidth);
-           if (num)
-               CFNumberGetValue (num, kCFNumberFloat32Type, &w);
-           num = CFDictionaryGetValue (properties, kCGImagePropertyPixelHeight);
-           if (num)
-               CFNumberGetValue (num, kCFNumberFloat32Type, &h);
-
-           size.width = w;
-           size.height = h;
-           
-           haveSize = YES;
-       }
+        CFDictionaryRef properties = [self propertiesAtIndex:0];
+        if (properties) {
+            CFNumberRef num = CFDictionaryGetValue (properties, kCGImagePropertyPixelWidth);
+            if (num)
+                CFNumberGetValue (num, kCFNumberFloat32Type, &w);
+            num = CFDictionaryGetValue (properties, kCGImagePropertyPixelHeight);
+            if (num)
+                CFNumberGetValue (num, kCFNumberFloat32Type, &h);
+
+            size.width = w;
+            size.height = h;
+            
+            haveSize = YES;
+        }
     }
     
     return size;
 }
 
+- (CFDictionaryRef)propertiesAtIndex:(size_t)index
+{
+    size_t num = [self numberOfImages];
+    
+    if (imageProperties == 0 && num) {
+        imageProperties = (CFDictionaryRef *)malloc (num * sizeof(CFDictionaryRef));
+        size_t i;
+        for (i = 0; i < num; i++) {
+            imageProperties[i] = CGImageSourceGetPropertiesAtIndex (imageSource, i, 0);
+        }
+    }
+    
+    if (index < num) {
+        // If image properties are nil, try to get them again.  May have attempted to
+        // get them before enough data was available in the header.
+        if (imageProperties[index] == 0) {
+            imageProperties[index] = CGImageSourceGetPropertiesAtIndex (imageSource, index, 0);
+        }
+        
+        return imageProperties[index];
+    }
+        
+    return 0;
+}
+
 #define MINIMUM_DURATION (1.0/30.0)
 
+- (float)_frameDurationAt:(size_t)i
+{
+    CFDictionaryRef properties = [self propertiesAtIndex:i];
+    if (!properties) {
+        return 0.f;
+    }
+    
+    // FIXME:  Use constant instead of {GIF}
+    CFDictionaryRef GIFProperties = CFDictionaryGetValue (properties, @"{GIF}");
+    if (!GIFProperties) {
+        return 0.f;
+    }
+    
+    // FIXME:  Use constant instead of DelayTime
+    CFNumberRef num = CFDictionaryGetValue (GIFProperties, @"DelayTime");
+    if (!num) {
+        return 0.f;
+    }
+    
+    float duration = 0.f;
+    CFNumberGetValue (num, kCFNumberFloat32Type, &duration);
+    if (duration < MINIMUM_DURATION) {
+        /*
+            Many annoying ads specify a 0 duration to make an image flash
+            as quickly as possible.  However a zero duration is faster than
+            the refresh rate.  We need to pick a minimum duration.
+            
+            Browsers handle the minimum time case differently.  IE seems to use something
+            close to 1/30th of a second.  Konqueror uses 0.  The ImageMagick library
+            uses 1/100th.  The units in the GIF specification are 1/100th of second.
+            We will use 1/30th of second as the minimum time.
+        */
+        duration = MINIMUM_DURATION;
+    }
+    
+    return duration;
+}
+
 - (float)_frameDuration
 {
     if (!frameDurations) {
-       frameDurations = (float *)malloc (sizeof(float) * [self numberOfImages]);
-       
-       size_t i;
-       for (i = 0; i < [self numberOfImages]; i++) {
-           CFDictionaryRef properties = CGImageSourceGetPropertiesAtIndex (imageSource, i, 0);
-           if (!properties) {
-               frameDurations[i] = 0.f;
-               continue;
-           }
-               
-           // FIXME:  Use constant instead of {GIF}
-           CFDictionaryRef GIFProperties = CFDictionaryGetValue (properties, @"{GIF}");
-           if (!GIFProperties) {
-               frameDurations[i] = 0.f;
-               continue;
-           }
-           
-           // FIXME:  Use constant instead of DelayTime
-           CFNumberRef num = CFDictionaryGetValue (GIFProperties, @"DelayTime");
-           if (!num) {
-               frameDurations[i] = 0.f;
-               continue;
-           }
-           
-           float duration = 0.f;
-           CFNumberGetValue (num, kCFNumberFloat32Type, &duration);
-           if (duration < MINIMUM_DURATION) {
-               /*
-                   Many annoying ads specify a 0 duration to make an image flash
-                   as quickly as possible.  However a zero duration is faster than
-                   the refresh rate.  We need to pick a minimum duration.
-                   
-                   Browsers handle the minimum time case differently.  IE seems to use something
-                   close to 1/30th of a second.  Konqueror uses 0.  The ImageMagick library
-                   uses 1/100th.  The units in the GIF specification are 1/100th of second.
-                   We will use 1/30th of second as the minimum time.
-               */
-               duration = MINIMUM_DURATION;
-           }
-           frameDurations[i] = duration;
-       }
+        size_t i, num = [self numberOfImages];
+
+        frameDurations = (float *)malloc (sizeof(float) * num);
+        for (i = 0; i < num; i++) {
+            frameDurations[i] = [self _frameDurationAt:i];
+        }
     }
-    
+    else if (frameDurations[currentFrame] == 0.f) {
+            frameDurations[currentFrame] = [self _frameDurationAt:currentFrame];
+    }
+
     return frameDurations[currentFrame];
 }
 
index 82b32ceacce41ff9e50be8917586c0b3d5700cba..571647b793bffc306e49755ff55abdc333dc0ad0 100644 (file)
@@ -6,9 +6,9 @@
 
 @protocol WebCoreImageRenderer;
 
-//#ifndef OMIT_TIGER_FEATURES
-//#define USE_CGIMAGEREF YES
-//#endif
+#ifndef OMIT_TIGER_FEATURES
+#define USE_CGIMAGEREF YES
+#endif
 
 #ifdef USE_CGIMAGEREF
 @class WebImageData;
@@ -19,6 +19,9 @@
 
     WebImageData *imageData;
 
+    NSImage *nsimage;
+    NSData *TIFFData;
+    
     NSRect targetAnimationRect;
     
     NSSize adjustedSize;
index 73b2f708bb140e7787d472894c44ea302a8dc055..2c655e0b4d5a9700f0089342a88efbc1ddc396b5 100644 (file)
@@ -66,6 +66,8 @@
 {
     [MIMEType release];
     [imageData release];
+    [nsimage release];
+    [TIFFData release];
     [super dealloc];
 }
 
 
 - (NSData *)TIFFRepresentation
 {
-    CGImageRef image = [imageData imageAtIndex:0];
-    if (!image)
-        return 0;
+    if (!TIFFData) {
+        CGImageRef image = [imageData imageAtIndex:0];
+        if (!image)
+            return 0;
+            
+        CFMutableDataRef data = 0;
+        CGImageDestinationRef destination = 0;
         
-    CFMutableDataRef data = 0;
-    CGImageDestinationRef destination = 0;
-    
-    data = CFDataCreateMutable(NULL, 0);
-    // FIXME:  Use type kCGImageTypeIdentifierTIFF constant once is becomes available in the API
-    destination = CGImageDestinationCreateWithData (data, CFSTR("public.tiff"), 1, NULL);
-    if (destination) {
-        CGImageDestinationAddImage (destination, image, NULL);
-        CGImageDestinationFinalize (destination);
-        CFRelease (destination);
-    }
+        data = CFDataCreateMutable(NULL, 0);
+        // FIXME:  Use type kCGImageTypeIdentifierTIFF constant once is becomes available in the API
+        destination = CGImageDestinationCreateWithData (data, CFSTR("public.tiff"), 1, NULL);
+        if (destination) {
+            CGImageDestinationAddImage (destination, image, NULL);
+            if (!CGImageDestinationFinalize (destination)) {
+                ERROR ("Unable to create image\n");
+            }
+            CFRelease (destination);
+        }
 
-    return [(NSData *)data autorelease];
+        TIFFData = (NSData *)data;
+    }
+    
+    return TIFFData;
 }
 
 - (NSImage *)image
 {
-    // FIXME:  Implement
-    return nil;
+    if (!nsimage)
+        nsimage = [[NSImage alloc] initWithData:[self TIFFRepresentation]];
+    return nsimage;
 }
 
 @end