Improved Cairo image rendering by only building the surface from the portion of the...
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Feb 2006 22:46:43 +0000 (22:46 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Feb 2006 22:46:43 +0000 (22:46 +0000)
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@12668 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.vcproj/Image Viewer/ImageView.cpp
WebCore/WebCore.vcproj/WebCore/WebCore.vcproj
WebCore/platform/cairo/ImageSourceCairo.cpp
WebCore/platform/image-decoders/ImageDecoder.h
WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
WebCore/platform/image-decoders/png/PNGImageDecoder.cpp

index 5d00a24450167fa664f49cb215113776b07a30ed..ad4eee421301e5b4c9d2d5ea9fd5697e6b12eebf 100644 (file)
 
         * khtml/xml/Element.idl: Added.
 
+2006-02-08  Dave Hyatt <hyatt@apple.com>
+
+        Make the Cairo image surface only reflect the portion of
+        the image that has been decoded so far.   That way we don't
+        have to zero fill our RGBA32 buffers, and we avoid painting
+        the empty portion.
+
+        Reviewed by timo
+
+        * Viewer/ImageView.cpp:
+        * WebCore.vcproj/WebCore/WebCore.vcproj:
+        * platform/cairo/ImageSourceCairo.cpp:
+        (WebCore::createDecoder):
+        (WebCore::ImageSource::createFrameAtIndex):
+        * platform/image-decoders/ImageDecoder.h:
+        (WebCore::RGBA32Buffer::RGBA32Buffer):
+        (WebCore::RGBA32Buffer::height):
+        (WebCore::RGBA32Buffer::ensureHeight):
+        (WebCore::RGBA32Buffer::setStatus):
+        (WebCore::RGBA32Buffer::setDuration):
+        (WebCore::RGBA32Buffer::setIncludeInNextFrame):
+        * platform/image-decoders/gif/GIFImageDecoder.cpp:
+        (WebCore::GIFImageDecoder::haveDecodedRow):
+        (WebCore::GIFImageDecoder::frameComplete):
+        * platform/image-decoders/png/PNGImageDecoder.cpp:
+        (WebCore::PNGImageDecoder::rowAvailable):
+        (WebCore::PNGImageDecoder::pngComplete):
+
 2006-02-08  Dave Hyatt <hyatt@apple.com>
 
         Implement support for PNGs on Win32.  Includes support for
index 932f59a3e0a8318589bb0c72875368afb15bc5aa..7b4ff19d89e15d7a1d37e643e1a6d74d673594cd 100755 (executable)
@@ -84,10 +84,10 @@ void ImageView::OnDraw(CDC* pDC)
     // Fill with white.\r
     cairo_t* context = cairo_create(surface);\r
     cairo_rectangle(context, 0, 0, rect.right, rect.bottom);\r
-    cairo_set_source_rgb(context, 1.0, 1.0, 1.0);\r
+    cairo_set_source_rgb(context, 1.0, 0.0, 0.0);\r
     cairo_fill(context);\r
 \r
-    // Let's test scaling to double the size.\r
+    // Comment in to test scaling (doubles the size).\r
     float width = image->size().width(); // * 2;\r
     float height = image->size().height(); // * 2;\r
 \r
index f85d61b3b11607e959c1b6cde3cf443d3088b1c8..d6533a1c03fc011bb342b2438f8c7eaccb5caecb 100644 (file)
                                                >\r
                                        </File>\r
                                </Filter>\r
+                               <Filter\r
+                                       Name="jpeg"\r
+                                       >\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jcomapi.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jconfig.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdapimin.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdapistd.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdatadst.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdatasrc.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdcoefct.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdcolor.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdct.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jddctmgr.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdhuff.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdhuff.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdinput.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdmainct.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdmarker.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdmaster.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdmerge.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdphuff.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdpostct.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jdsample.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jerror.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jerror.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jfdctflt.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jfdctfst.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jfdctint.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jidctflt.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jidctfst.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jidctint.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jinclude.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jmemmgr.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jmemnobs.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jmemsys.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jmorecfg.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jpegint.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jpeglib.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jquant1.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jquant2.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jutils.c"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jversion.h"\r
+                                               >\r
+                                       </File>\r
+                                       <File\r
+                                               RelativePath="..\..\platform\image-decoders\jpeg\jwinfig.h"\r
+                                               >\r
+                                       </File>\r
+                               </Filter>\r
                        </Filter>\r
                        <Filter\r
                                Name="cairo"\r
index 3021bcc0ab95545e511231605c111badeaaeb395..74fc4710c2034c0e550efdf978593b62c1ac12f9 100755 (executable)
@@ -57,9 +57,8 @@ ImageDecoder* createDecoder(const ByteArray& data)
     // JPEG
     if (uContents[0]==0xFF &&
         uContents[1]==0xD8 &&
-        uContents[2]==0xFF) {
+        uContents[2]==0xFF)
         return 0;
-    }
 
     // BMP
     if (strncmp(contents, "BM", 2) == 0) {
@@ -144,7 +143,7 @@ NativeImagePtr ImageSource::createFrameAtIndex(size_t index)
     return cairo_image_surface_create_for_data((unsigned char*)buffer.bytes().data(),
                                                CAIRO_FORMAT_ARGB32,
                                                size().width(),
-                                               size().height(),
+                                               buffer.height(),
                                                size().width()*4);
 }
 
index b570bc4660156c2f930f4812fdad706e8635ccd3..e3a66e68182dd2fdf38a92dc9296644e4dbb9421 100755 (executable)
@@ -44,17 +44,20 @@ class RGBA32Buffer
 public:
     enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
 
-    RGBA32Buffer() : m_status(FrameEmpty), m_duration(0), m_includeInNextFrame(false)
+    RGBA32Buffer() : m_height(0), m_status(FrameEmpty), m_duration(0), m_includeInNextFrame(false)
     {} 
 
-    void setStatus(FrameStatus s) { m_status = s; }
-    void setDuration(unsigned duration) { m_duration = duration; }
-    void setIncludeInNextFrame(bool n) { m_includeInNextFrame = n; }
-
     RGBA32Array& bytes() { return m_bytes; }
+    unsigned height() { return m_height; }
     FrameStatus status() const { return m_status; }
     unsigned duration() const { return m_duration; }
     bool includeInNextFrame() const { return m_includeInNextFrame; }
+  
+    void ensureHeight(unsigned rowIndex) { if (rowIndex > m_height) m_height = rowIndex; }
+
+    void setStatus(FrameStatus s) { m_status = s; }
+    void setDuration(unsigned duration) { m_duration = duration; }
+    void setIncludeInNextFrame(bool n) { m_includeInNextFrame = n; }
 
     static void setRGBA(unsigned& pos, unsigned r, unsigned b, unsigned g, unsigned a)
     {
@@ -74,6 +77,7 @@ public:
 
 private:
     RGBA32Array m_bytes;
+    unsigned m_height; // The height (the number of rows we've fully decoded).
     FrameStatus m_status; // Whether or not this frame is completely finished decoding.
     unsigned m_duration; // The animation delay.
     bool m_includeInNextFrame; // Whether or not the next buffer should be initially populated with our data.
index 279973c826cc862b0da5b9200b6bb9e58588c907..d592e9639c5b06436a4081f561798b854bcb277d 100755 (executable)
@@ -211,12 +211,12 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
         
         // If the disposal method of the previous frame said to stick around, then we need
         // to copy that frame into our frame.
-        if (frameIndex > 0 && m_frameBufferCache[frameIndex-1].includeInNextFrame())
+        if (frameIndex > 0 && m_frameBufferCache[frameIndex-1].includeInNextFrame()) {
             bytes.duplicate(m_frameBufferCache[frameIndex-1].bytes());
-        else {
-            bytes.resize(m_size.width() * m_size.height());
-            bytes.fill(0);
+            buffer.ensureHeight(m_size.height());
         }
+        else
+            bytes.resize(m_size.width() * m_size.height());
 
         // Update our status to be partially complete.
         buffer.setStatus(RGBA32Buffer::FramePartial);
@@ -269,17 +269,15 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
             currDst += width;
         }
     }
-}   
+
+    // Our partial height is rowNumber + 1, e.g., row 2 is the 3rd row, so that's a height of 3.
+    // Adding in repeatCount - 1 to rowNumber + 1 works out to just be rowNumber + repeatCount.
+    buffer.ensureHeight(rowNumber + repeatCount);
+}
 
 void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, bool includeInNextFrame)
 {
     RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
-    
-    // Degenerate GIFS can sometimes result in empty frames.  Ensure we at least have a filled
-    // frame with the correct width/height.
-    if (buffer.status() == RGBA32Buffer::FrameEmpty)
-        haveDecodedRow(frameIndex, 0, 0, 0, 0);
-
     buffer.setStatus(RGBA32Buffer::FrameComplete);
     buffer.setDuration(frameDuration);
     buffer.setIncludeInNextFrame(includeInNextFrame);
index db91b600820af140ecfa3332066fc9421cfc5956..98e5a044d64aa71fc0ff869f249f6d9314a23bf8 100755 (executable)
@@ -307,7 +307,7 @@ void rowAvailable(png_structp png, png_bytep rowBuffer,
     static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass);
 }
 
-void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned int rowIndex, int interlacePass)
+void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass)
 {
     if (m_frameBufferCache.isEmpty())
         return;
@@ -318,7 +318,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned int rowInd
         // Let's resize our buffer now to the correct width/height.
         RGBA32Array& bytes = buffer.bytes();
         bytes.resize(m_size.width() * m_size.height());
-        bytes.fill(0);
 
         // Update our status to be partially complete.
         buffer.setStatus(RGBA32Buffer::FramePartial);
@@ -380,6 +379,8 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned int rowInd
         unsigned alpha = (hasAlpha ? *row++ : 255);
         RGBA32Buffer::setRGBA(*dst++, red, blue, green, alpha);
     }
+
+    buffer.ensureHeight(rowIndex + 1);
 }
 
 void pngComplete(png_structp png, png_infop info)
@@ -394,8 +395,6 @@ void PNGImageDecoder::pngComplete()
 
     // Hand back an appropriately sized buffer, even if the image ended up being empty.
     RGBA32Buffer& buffer = m_frameBufferCache[0];
-    if (buffer.status() == RGBA32Buffer::FrameEmpty)
-        rowAvailable(0, 0, 0);
     buffer.setStatus(RGBA32Buffer::FrameComplete);
 }