summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/cg
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/platform/graphics/cg
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/platform/graphics/cg')
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp41
-rw-r--r--Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp123
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp14
-rw-r--r--Source/WebCore/platform/graphics/cg/ImageCG.cpp4
4 files changed, 162 insertions, 20 deletions
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index c19bd72..187d296 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -26,7 +26,7 @@
#include "config.h"
-#if ENABLE(3D_CANVAS)
+#if ENABLE(WEBGL)
#include "GraphicsContext3D.h"
#include "GraphicsContextCG.h"
@@ -105,7 +105,7 @@ bool GraphicsContext3D::getImageData(Image* image,
decoder.setData(image->data(), true);
if (!decoder.frameCount())
return false;
- decodedImage = decoder.createFrameAtIndex(0);
+ decodedImage.adoptCF(decoder.createFrameAtIndex(0));
cgImage = decodedImage.get();
} else
cgImage = image->nativeImageForCurrentFrame();
@@ -116,6 +116,34 @@ bool GraphicsContext3D::getImageData(Image* image,
size_t height = CGImageGetHeight(cgImage);
if (!width || !height)
return false;
+
+ // See whether the image is using an indexed color space, and if
+ // so, re-render it into an RGB color space. The image re-packing
+ // code requires color data, not color table indices, for the
+ // image data.
+ CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage);
+ CGColorSpaceModel model = CGColorSpaceGetModel(colorSpace);
+ if (model == kCGColorSpaceModelIndexed) {
+ RetainPtr<CGContextRef> bitmapContext;
+ // FIXME: we should probably manually convert the image by indexing into
+ // the color table, which would allow us to avoid premultiplying the
+ // alpha channel. Creation of a bitmap context with an alpha channel
+ // doesn't seem to work unless it's premultiplied.
+ bitmapContext.adoptCF(CGBitmapContextCreate(0, width, height, 8, width * 4,
+ deviceRGBColorSpaceRef(),
+ kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+ if (!bitmapContext)
+ return false;
+
+ CGContextSetBlendMode(bitmapContext.get(), kCGBlendModeCopy);
+ CGContextSetInterpolationQuality(bitmapContext.get(), kCGInterpolationNone);
+ CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, width, height), cgImage);
+
+ // Now discard the original CG image and replace it with a copy from the bitmap context.
+ decodedImage.adoptCF(CGBitmapContextCreateImage(bitmapContext.get()));
+ cgImage = decodedImage.get();
+ }
+
size_t bitsPerComponent = CGImageGetBitsPerComponent(cgImage);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
if (bitsPerComponent != 8 && bitsPerComponent != 16)
@@ -168,10 +196,11 @@ bool GraphicsContext3D::getImageData(Image* image,
AlphaFormat alphaFormat = AlphaFormatNone;
switch (CGImageGetAlphaInfo(cgImage)) {
case kCGImageAlphaPremultipliedFirst:
- // This path is only accessible for MacOS earlier than 10.6.4.
// This is a special case for texImage2D with HTMLCanvasElement input,
- // in which case image->data() should be null.
- ASSERT(!image->data());
+ // in which case image->data() should be null, or indexed color models,
+ // where we need premultiplied alpha to create the bitmap context
+ // successfully.
+ ASSERT(!image->data() || model == kCGColorSpaceModelIndexed);
if (!premultiplyAlpha)
neededAlphaOp = AlphaDoUnmultiply;
alphaFormat = AlphaFormatFirst;
@@ -254,4 +283,4 @@ void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag
} // namespace WebCore
-#endif // ENABLE(3D_CANVAS)
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index bcfc37b..3591479 100644
--- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -35,6 +35,7 @@
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
+#include "ShadowBlur.h"
#include <CoreGraphics/CoreGraphics.h>
#include <wtf/MathExtras.h>
@@ -165,9 +166,9 @@ void GraphicsContext::drawRect(const IntRect& rect)
setCGFillColor(context, strokeColor(), strokeColorSpace());
CGRect rects[4] = {
FloatRect(rect.x(), rect.y(), rect.width(), 1),
- FloatRect(rect.x(), rect.bottom() - 1, rect.width(), 1),
+ FloatRect(rect.x(), rect.maxY() - 1, rect.width(), 1),
FloatRect(rect.x(), rect.y() + 1, 1, rect.height() - 2),
- FloatRect(rect.right() - 1, rect.y() + 1, 1, rect.height() - 2)
+ FloatRect(rect.maxX() - 1, rect.y() + 1, 1, rect.height() - 2)
};
CGContextFillRects(context, rects, 4);
if (oldFillColor != strokeColor())
@@ -563,7 +564,7 @@ void GraphicsContext::fillPath(const Path& path)
CGContextClip(layerContext);
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.left(), rect.top()), layer);
+ CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
CGLayerRelease(layer);
} else {
CGContextBeginPath(context);
@@ -616,6 +617,16 @@ void GraphicsContext::strokePath(const Path& path)
CGContextStrokePath(context);
}
+static float radiusToLegacyRadius(float radius)
+{
+ return radius > 8 ? 8 + 4 * sqrt((radius - 8) / 2) : radius;
+}
+
+static bool hasBlurredShadow(const GraphicsContextState& state)
+{
+ return state.shadowColor.isValid() && state.shadowColor.alpha() && state.shadowBlur;
+}
+
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
@@ -626,11 +637,16 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_state.fillGradient) {
CGContextSaveGState(context);
if (hasShadow()) {
- CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform());
CGLayerRef layer = CGLayerCreateWithContext(context, CGSizeMake(rect.width(), rect.height()), 0);
CGContextRef layerContext = CGLayerGetContext(layer);
+
+ CGContextTranslateCTM(layerContext, -rect.x(), -rect.y());
+ CGContextAddRect(layerContext, rect);
+ CGContextClip(layerContext);
+
+ CGContextConcatCTM(layerContext, m_state.fillGradient->gradientSpaceTransform());
m_state.fillGradient->paint(layerContext);
- CGContextDrawLayerAtPoint(context, CGPointMake(rect.left(), rect.top()), layer);
+ CGContextDrawLayerAtPoint(context, CGPointMake(rect.x(), rect.y()), layer);
CGLayerRelease(layer);
} else {
CGContextClipToRect(context, rect);
@@ -643,7 +659,22 @@ void GraphicsContext::fillRect(const FloatRect& rect)
if (m_state.fillPattern)
applyFillPattern();
+
+ bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
+ }
+
CGContextFillRect(context, rect);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace)
@@ -658,7 +689,21 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, color, colorSpace);
+ bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
+ }
+
CGContextFillRect(context, rect);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, oldFillColor, oldColorSpace);
@@ -678,12 +723,72 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
Path path;
path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
+
+ bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms; // Don't use ShadowBlur for canvas yet.
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
+ }
+
fillPath(path);
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
+
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, oldFillColor, oldColorSpace);
}
+void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const RoundedIntRect& roundedHoleRect, const Color& color, ColorSpace colorSpace)
+{
+ if (paintingDisabled())
+ return;
+
+ CGContextRef context = platformContext();
+
+ Path path;
+ path.addRect(rect);
+
+ if (!roundedHoleRect.radii().isZero())
+ path.addRoundedRect(roundedHoleRect.rect(), roundedHoleRect.radii().topLeft(), roundedHoleRect.radii().topRight(), roundedHoleRect.radii().bottomLeft(), roundedHoleRect.radii().bottomRight());
+ else
+ path.addRect(roundedHoleRect.rect());
+
+ WindRule oldFillRule = fillRule();
+ Color oldFillColor = fillColor();
+ ColorSpace oldFillColorSpace = fillColorSpace();
+
+ setFillRule(RULE_EVENODD);
+ setFillColor(color, colorSpace);
+
+ // fillRectWithRoundedHole() assumes that the edges of rect are clipped out, so we only care about shadows cast around inside the hole.
+ bool drawOwnShadow = hasBlurredShadow(m_state) && !m_state.shadowsIgnoreTransforms;
+ if (drawOwnShadow) {
+ float shadowBlur = m_state.shadowsUseLegacyRadius ? radiusToLegacyRadius(m_state.shadowBlur) : m_state.shadowBlur;
+
+ // Turn off CG shadows.
+ CGContextSaveGState(context);
+ CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
+
+ ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+ contextShadow.drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii());
+ }
+
+ fillPath(path);
+
+ if (drawOwnShadow)
+ CGContextRestoreGState(context);
+
+ setFillRule(oldFillRule);
+ setFillColor(oldFillColor, oldFillColorSpace);
+}
+
void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
@@ -722,6 +827,11 @@ void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
CGContextClip(context);
}
+IntRect GraphicsContext::clipBounds() const
+{
+ return enclosingIntRect(CGContextGetClipBoundingBox(platformContext()));
+}
+
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
{
if (paintingDisabled())
@@ -766,6 +876,9 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
{
if (paintingDisabled())
return;
+
+ // FIXME: we could avoid the shadow setup cost when we know we'll render the shadow ourselves.
+
CGFloat xOffset = offset.width();
CGFloat yOffset = offset.height();
CGFloat blurRadius = blur;
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 295f632..ab5907e 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -267,7 +267,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
unsigned char* data = result->data();
- if (rect.x() < 0 || rect.y() < 0 || rect.right() > size.width() || rect.bottom() > size.height())
+ if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height())
memset(data, 0, result->length());
int originx = rect.x();
@@ -276,7 +276,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
destx = -originx;
originx = 0;
}
- int endx = rect.right();
+ int endx = rect.maxX();
if (endx > size.width())
endx = size.width();
int numColumns = endx - originx;
@@ -287,7 +287,7 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
desty = -originy;
originy = 0;
}
- int endy = rect.bottom();
+ int endy = rect.maxY();
if (endy > size.height())
endy = size.height();
int numRows = endy - originy;
@@ -377,9 +377,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destx >= 0);
ASSERT(destx < size.width());
ASSERT(originx >= 0);
- ASSERT(originx <= sourceRect.right());
+ ASSERT(originx <= sourceRect.maxX());
- int endx = destPoint.x() + sourceRect.right();
+ int endx = destPoint.x() + sourceRect.maxX();
ASSERT(endx <= size.width());
int numColumns = endx - destx;
@@ -389,9 +389,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(desty >= 0);
ASSERT(desty < size.height());
ASSERT(originy >= 0);
- ASSERT(originy <= sourceRect.bottom());
+ ASSERT(originy <= sourceRect.maxY());
- int endy = destPoint.y() + sourceRect.bottom();
+ int endy = destPoint.y() + sourceRect.maxY();
ASSERT(endy <= size.height());
int numRows = endy - desty;
diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
index dfee96a..08f65bd 100644
--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -204,7 +204,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
adjustedDestRect.setHeight(subimageRect.height() / yScale);
image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
- if (currHeight < srcRect.bottom()) {
+ if (currHeight < srcRect.maxY()) {
ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
}
@@ -224,7 +224,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const F
// Flip the coords.
CGContextScaleCTM(context, 1, -1);
- adjustedDestRect.setY(-adjustedDestRect.bottom());
+ adjustedDestRect.setY(-adjustedDestRect.maxY());
// Adjust the color space.
image = imageWithColorSpace(image.get(), styleColorSpace);