Image::Image()
: m_currentFrame(0), m_frames(0), m_animationObserver(0),
m_frameTimer(0), m_repetitionCount(0), m_repetitionsComplete(0),
- m_animatingImageType(true), m_animationFinished(0),
+ m_isSolidColor(false), m_animatingImageType(true), m_animationFinished(false),
m_haveSize(false), m_sizeAvailable(false)
{
initNativeData();
Image::Image(ImageAnimationObserver* observer, bool isPDF)
: m_currentFrame(0), m_frames(0), m_animationObserver(0),
m_frameTimer(0), m_repetitionCount(0), m_repetitionsComplete(0),
- m_animatingImageType(true), m_animationFinished(0),
+ m_isSolidColor(false), m_animatingImageType(true), m_animationFinished(false),
m_haveSize(false), m_sizeAvailable(false)
{
initNativeData();
// Destroy the cached images and release them.
if (m_frames.size()) {
m_frames.last().clear();
+ m_isSolidColor = false;
invalidateNativeData();
}
}
m_frames.resize(numFrames);
m_frames[index].m_frame = m_source.createFrameAtIndex(index);
+ checkForSolidColor();
+
if (shouldAnimate())
m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
#ifndef IMAGE_H_
#define IMAGE_H_
+#include "Color.h"
#include "GraphicsTypes.h"
#include "ImageSource.h"
#include "IntSize.h"
ImageAnimationObserver* animationObserver() const { return m_animationObserver; }
enum TileRule { StretchTile, RoundTile, RepeatTile };
-
+
#if __APPLE__
// Accessors for native image formats.
CGImageRef getCGImageRef();
// PDF
void setIsPDF() { m_isPDF = true; }
-
-private:
- void checkForSolidColor(CGImageRef);
#endif
private:
// Invalidation of native data.
void invalidateNativeData();
+ // Checks to see if the image is a 1x1 solid color. We optimize these images and just do a fill rect instead.
+ void checkForSolidColor();
+
// Members
Vector<char> m_data; // The encoded raw data for the image.
ImageSource m_source;
mutable NSImage* m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one.
mutable CFDataRef m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one.
PDFDocumentImage* m_PDFDoc;
- CGColorRef m_solidColor; // Will be 0 if transparent.
- bool m_isSolidColor : 1; // If the image is 1x1 with no alpha, we can just do a rect fill when painting/tiling.
- bool m_isPDF : 1;
+ bool m_isPDF;
#endif
- bool m_animatingImageType : 1; // Whether or not we're an image type that is capable of animating (GIF).
- bool m_animationFinished : 1; // Whether or not we've completed the entire animation.
+ Color m_solidColor; // If we're a 1x1 solid color, this is the color to use to fill.
+ bool m_isSolidColor; // Whether or not we are a 1x1 solid image.
+
+ bool m_animatingImageType; // Whether or not we're an image type that is capable of animating (GIF).
+ bool m_animationFinished; // Whether or not we've completed the entire animation.
- mutable bool m_haveSize : 1; // Whether or not our |m_size| member variable has the final overall image size yet.
- bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
+ mutable bool m_haveSize; // Whether or not our |m_size| member variable has the final overall image size yet.
+ bool m_sizeAvailable; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
};
}
{
m_nsImage = 0;
m_tiffRep = 0;
- m_solidColor = 0;
- m_isSolidColor = 0;
m_isPDF = false;
m_PDFDoc = 0;
}
CFRelease(m_tiffRep);
m_tiffRep = 0;
}
-
- m_isSolidColor = false;
- if (m_solidColor) {
- CFRelease(m_solidColor);
- m_solidColor = 0;
- }
}
Image* Image::loadResource(const char *name)
// Drawing Routines
-static void fillSolidColorInRect(GraphicsContext* context, CGColorRef color, CGRect rect, CompositeOperator op)
-{
- if (color) {
- context->save();
- CGContextSetFillColorWithColor(context->platformContext(), color);
- context->setCompositeOperation(op);
- CGContextFillRect(context->platformContext(), rect);
- context->restore();
- }
-}
-
-void Image::checkForSolidColor(CGImageRef image)
+void Image::checkForSolidColor()
{
- m_isSolidColor = false;
- if (m_solidColor) {
- CFRelease(m_solidColor);
- m_solidColor = 0;
- }
-
- // Currently we only check for solid color in the important special case of a 1x1 image.
- if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
- CGFloat pixel[4]; // RGBA
- CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
-// This #if won't be needed once the CG header that includes kCGBitmapByteOrder32Host is included in the OS.
-#if __ppc__
- CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
- kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents);
-#else
- CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
- kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents | kCGBitmapByteOrder32Host);
-#endif
- if (bmap) {
- GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
- CGRect dst = { {0, 0}, {1, 1} };
- CGContextDrawImage(bmap, dst, image);
- if (pixel[3] > 0)
- m_solidColor = CGColorCreate(space,pixel);
- m_isSolidColor = true;
- CFRelease(bmap);
- }
- CFRelease(space);
+ if (frameCount() > 1)
+ m_isSolidColor = false;
+ else {
+ CGImageRef image = frameAtIndex(0);
+
+ // Currently we only check for solid color in the important special case of a 1x1 image.
+ if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
+ CGFloat pixel[4]; // RGBA
+ CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+ CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
+ kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents | kCGBitmapByteOrder32Host);
+ if (bmap) {
+ GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
+ CGRect dst = { {0, 0}, {1, 1} };
+ CGContextDrawImage(bmap, dst, image);
+ m_solidColor = Color(int(pixel[0] * 255), int(pixel[1] * 255), int(pixel[2] * 255), int(pixel[3] * 255));
+ m_isSolidColor = true;
+ CFRelease(bmap);
+ }
+ CFRelease(space);
+ }
}
}
if (!image) // If it's too early we won't have an image yet.
return;
- if (m_isSolidColor && m_currentFrame == 0)
- return fillSolidColorInRect(ctxt, m_solidColor, ir, compositeOp);
+ if (m_isSolidColor && m_currentFrame == 0) {
+ if (m_solidColor.alpha() > 0) {
+ ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && compositeOp == CompositeSourceOver ? CompositeCopy : compositeOp);
+ ctxt->fillRect(ir, m_solidColor);
+ }
+ return;
+ }
CGContextRef context = ctxt->platformContext();
-
ctxt->save();
-
+
// Get the height (in adjusted, i.e. scaled, coords) of the portion of the image
// that is currently decoded. This could be less that the actual height.
CGSize selfSize = size(); // full image size, in pixels
static const CGPatternCallbacks patternCallbacks = { 0, drawPattern, NULL };
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint,
- const FloatSize& tileSize, CompositeOperator op)
+ const FloatSize& tileSize, CompositeOperator op)
{
CGImageRef image = frameAtIndex(m_currentFrame);
if (!image)
return;
- if (m_currentFrame == 0 && m_isSolidColor) {
- fillSolidColorInRect(ctxt, m_solidColor, destRect, op);
+ if (m_isSolidColor && m_currentFrame == 0) {
+ if (m_solidColor.alpha() > 0) {
+ ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+ ctxt->fillRect(destRect, m_solidColor);
+ }
return;
}
// FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule,
- TileRule vRule, CompositeOperator op)
+ TileRule vRule, CompositeOperator op)
{
CGImageRef image = frameAtIndex(m_currentFrame);
if (!image)
return;
- if (m_currentFrame == 0 && m_isSolidColor)
- return fillSolidColorInRect(ctxt, m_solidColor, dstRect, op);
+ if (m_isSolidColor && m_currentFrame == 0) {
+ if (m_solidColor.alpha() > 0) {
+ ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+ ctxt->fillRect(dstRect, m_solidColor);
+ }
+ return;
+ }
ctxt->save();