* 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
// 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
>\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
// JPEG
if (uContents[0]==0xFF &&
uContents[1]==0xD8 &&
- uContents[2]==0xFF) {
+ uContents[2]==0xFF)
return 0;
- }
// BMP
if (strncmp(contents, "BM", 2) == 0) {
return cairo_image_surface_create_for_data((unsigned char*)buffer.bytes().data(),
CAIRO_FORMAT_ARGB32,
size().width(),
- size().height(),
+ buffer.height(),
size().width()*4);
}
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)
{
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.
// 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);
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);
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;
// 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);
unsigned alpha = (hasAlpha ? *row++ : 255);
RGBA32Buffer::setRGBA(*dst++, red, blue, green, alpha);
}
+
+ buffer.ensureHeight(rowIndex + 1);
}
void pngComplete(png_structp png, png_infop info)
// 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);
}