summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cg
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-18 15:36:45 +0100
committerBen Murdoch <benm@google.com>2009-08-18 19:20:06 +0100
commitd227fc870c7a697500a3c900c31baf05fb9a8524 (patch)
treea3fa109aa5bf52fef562ac49d97a2f723889cc71 /WebCore/platform/graphics/cg
parentf2c627513266faa73f7669058d98c60769fb3524 (diff)
downloadexternal_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.zip
external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.gz
external_webkit-d227fc870c7a697500a3c900c31baf05fb9a8524.tar.bz2
Merge WebKit r47420
Diffstat (limited to 'WebCore/platform/graphics/cg')
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp346
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp61
2 files changed, 216 insertions, 191 deletions
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index ab8eb3c..f1e6a1f 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -28,14 +28,15 @@
#include "config.h"
#include "GraphicsContext.h"
-#include "TransformationMatrix.h"
#include "FloatConversion.h"
-#include "GraphicsContextPrivate.h"
#include "GraphicsContextPlatformPrivateCG.h"
+#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "KURL.h"
#include "Path.h"
#include "Pattern.h"
+#include "TransformationMatrix.h"
+
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGPDFContext.h>
#include <wtf/MathExtras.h>
@@ -178,19 +179,19 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
int patWidth = 0;
switch (strokeStyle()) {
- case NoStroke:
- case SolidStroke:
- break;
- case DottedStroke:
- patWidth = (int)width;
- break;
- case DashedStroke:
- patWidth = 3 * (int)width;
- break;
+ case NoStroke:
+ case SolidStroke:
+ break;
+ case DottedStroke:
+ patWidth = (int)width;
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)width;
+ break;
}
CGContextRef context = platformContext();
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, false);
@@ -221,7 +222,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -235,7 +236,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
patternOffset = (patWidth - remainder)/2;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
@@ -248,7 +249,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
if (patWidth)
CGContextRestoreGState(context);
-
+
if (shouldAntialias())
CGContextSetShouldAntialias(context, true);
}
@@ -263,7 +264,7 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
if (paintingDisabled())
return;
-
+
CGContextRef context = platformContext();
CGContextBeginPath(context);
float r = (float)rect.width() / 2;
@@ -275,25 +276,25 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan)
-{
+{
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f)
return;
-
+
CGContextRef context = platformContext();
CGContextSaveGState(context);
CGContextBeginPath(context);
CGContextSetShouldAntialias(context, false);
-
+
int x = rect.x();
int y = rect.y();
float w = (float)rect.width();
float h = (float)rect.height();
float scaleFactor = h / w;
float reverseScaleFactor = w / h;
-
+
if (w != h)
scale(FloatSize(1, scaleFactor));
-
+
float hRadius = w / 2;
float vRadius = h / 2;
float fa = startAngle;
@@ -304,22 +305,21 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (w != h)
scale(FloatSize(1, reverseScaleFactor));
-
-
+
float width = strokeThickness();
int patWidth = 0;
-
+
switch (strokeStyle()) {
- case DottedStroke:
- patWidth = (int)(width / 2);
- break;
- case DashedStroke:
- patWidth = 3 * (int)(width / 2);
- break;
- default:
- break;
+ case DottedStroke:
+ patWidth = (int)(width / 2);
+ break;
+ case DashedStroke:
+ patWidth = 3 * (int)(width / 2);
+ break;
+ default:
+ break;
}
-
+
if (patWidth) {
// Example: 80 pixels with a width of 30 pixels.
// Remainder is 20. The maximum pixels of line we could paint
@@ -329,7 +329,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
distance = static_cast<int>((piFloat * hRadius) / 2.0f);
else // We are elliptical and will have to estimate the distance
distance = static_cast<int>((piFloat * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0f)) / 2.0f);
-
+
int remainder = distance % patWidth;
int coverage = distance - remainder;
int numSegments = coverage / patWidth;
@@ -339,7 +339,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (patWidth == 1)
patternOffset = 1.0f;
else {
- bool evenNumberOfSegments = numSegments % 2 == 0;
+ bool evenNumberOfSegments = !(numSegments % 2);
if (remainder)
evenNumberOfSegments = !evenNumberOfSegments;
if (evenNumberOfSegments) {
@@ -353,13 +353,13 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
patternOffset = (patWidth - remainder) / 2.0f;
}
}
-
+
const CGFloat dottedLine[2] = { patWidth, patWidth };
CGContextSetLineDash(context, patternOffset, dottedLine, 2);
}
CGContextStrokePath(context);
-
+
CGContextRestoreGState(context);
}
@@ -375,7 +375,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, antialiased);
-
+
CGContextBeginPath(context);
CGContextMoveToPoint(context, points[0].x(), points[0].y());
for (size_t i = 1; i < npoints; i++)
@@ -383,7 +383,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
CGContextClosePath(context);
drawPath();
-
+
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, shouldAntialias());
}
@@ -391,7 +391,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
-
+
CGPatternRef platformPattern = m_common->state.strokePattern.get()->createPlatformPattern(getCTM());
if (!platformPattern)
return;
@@ -463,7 +463,7 @@ void GraphicsContext::drawPath()
strokePath();
return;
}
-
+
if (state.fillColorSpace == PatternColorSpace)
applyFillPattern();
if (state.strokeColorSpace == PatternColorSpace)
@@ -599,7 +599,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGRect rects[2] = { CGContextGetClipBoundingBox(platformContext()), rect };
CGContextBeginPath(platformContext());
CGContextAddRects(platformContext(), rects, 2);
@@ -610,7 +610,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddEllipseInRect(platformContext(), rect);
@@ -639,13 +639,13 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
clip(rect);
CGContextRef context = platformContext();
-
+
// Add outer ellipse
CGContextAddEllipseInRect(context, CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()));
// Add inner ellipse.
CGContextAddEllipseInRect(context, CGRectMake(rect.x() + thickness, rect.y() + thickness,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
-
+
CGContextEOClip(context);
}
@@ -653,7 +653,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer
{
if (paintingDisabled())
return;
-
+
CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height());
CGContextScaleCTM(platformContext(), 1, -1);
CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef());
@@ -734,7 +734,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Col
CGColorRef colorCG = createCGColor(color);
CGContextSetShadowWithColor(context,
CGSizeMake(width, height),
- blurRadius,
+ blurRadius,
colorCG);
CGColorRelease(colorCG);
}
@@ -799,15 +799,15 @@ void GraphicsContext::setLineCap(LineCap cap)
if (paintingDisabled())
return;
switch (cap) {
- case ButtCap:
- CGContextSetLineCap(platformContext(), kCGLineCapButt);
- break;
- case RoundCap:
- CGContextSetLineCap(platformContext(), kCGLineCapRound);
- break;
- case SquareCap:
- CGContextSetLineCap(platformContext(), kCGLineCapSquare);
- break;
+ case ButtCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapButt);
+ break;
+ case RoundCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapRound);
+ break;
+ case SquareCap:
+ CGContextSetLineCap(platformContext(), kCGLineCapSquare);
+ break;
}
}
@@ -821,15 +821,15 @@ void GraphicsContext::setLineJoin(LineJoin join)
if (paintingDisabled())
return;
switch (join) {
- case MiterJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
- break;
- case RoundJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
- break;
- case BevelJoin:
- CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
- break;
+ case MiterJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinMiter);
+ break;
+ case RoundJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinRound);
+ break;
+ case BevelJoin:
+ CGContextSetLineJoin(platformContext(), kCGLineJoinBevel);
+ break;
}
}
@@ -858,7 +858,7 @@ void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
return;
-
+
CGContextBeginPath(platformContext());
CGContextAddRect(platformContext(), CGContextGetClipBoundingBox(platformContext()));
CGContextAddPath(platformContext(), path.platformPath());
@@ -909,9 +909,9 @@ TransformationMatrix GraphicsContext::getCTM() const
FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
{
- // It is not enough just to round to pixels in device space. The rotation part of the
+ // It is not enough just to round to pixels in device space. The rotation part of the
// affine transform matrix to device space can mess with this conversion if we have a
- // rotating image like the hands of the world clock widget. We just need the scale, so
+ // rotating image like the hands of the world clock widget. We just need the scale, so
// we get the affine transform matrix and extract the scale.
if (m_data->m_userToDeviceTransformKnownToBeIdentity)
@@ -934,11 +934,11 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect)
deviceOrigin.y = roundf(deviceOrigin.y);
deviceLowerRight.x = roundf(deviceLowerRight.x);
deviceLowerRight.y = roundf(deviceLowerRight.y);
-
+
// Don't let the height or width round to 0 unless either was originally 0
- if (deviceOrigin.y == deviceLowerRight.y && rect.height() != 0)
+ if (deviceOrigin.y == deviceLowerRight.y && rect.height())
deviceLowerRight.y += 1;
- if (deviceOrigin.x == deviceLowerRight.x && rect.width() != 0)
+ if (deviceOrigin.x == deviceLowerRight.x && rect.width())
deviceLowerRight.x += 1;
FloatPoint roundedOrigin = FloatPoint(deviceOrigin.x / deviceScaleX, deviceOrigin.y / deviceScaleY);
@@ -984,13 +984,13 @@ void GraphicsContext::drawLineForText(const IntPoint& point, int width, bool pri
}
}
}
-
+
if (fillColor() != strokeColor())
setCGFillColor(platformContext(), strokeColor());
CGContextFillRect(platformContext(), CGRectMake(x, y, lineLength, thickness));
if (fillColor() != strokeColor())
setCGFillColor(platformContext(), fillColor());
-
+
if (restoreAntialiasMode)
CGContextSetShouldAntialias(platformContext(), true);
}
@@ -999,11 +999,11 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect)
{
if (paintingDisabled())
return;
-
+
CFURLRef urlRef = link.createCFURL();
if (urlRef) {
CGContextRef context = platformContext();
-
+
// Get the bounding box to handle clipping.
CGRect box = CGContextGetClipBoundingBox(context);
@@ -1022,28 +1022,28 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality mode)
{
if (paintingDisabled())
return;
-
+
CGInterpolationQuality quality = kCGInterpolationDefault;
switch (mode) {
- case InterpolationDefault:
- quality = kCGInterpolationDefault;
- break;
- case InterpolationNone:
- quality = kCGInterpolationNone;
- break;
- case InterpolationLow:
- quality = kCGInterpolationLow;
- break;
-
- // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
- case InterpolationMedium:
+ case InterpolationDefault:
+ quality = kCGInterpolationDefault;
+ break;
+ case InterpolationNone:
+ quality = kCGInterpolationNone;
+ break;
+ case InterpolationLow:
+ quality = kCGInterpolationLow;
+ break;
+
+ // Fall through to InterpolationHigh if kCGInterpolationMedium is not available
+ case InterpolationMedium:
#if HAVE(CG_INTERPOLATION_MEDIUM)
- quality = kCGInterpolationMedium;
- break;
+ quality = kCGInterpolationMedium;
+ break;
#endif
- case InterpolationHigh:
- quality = kCGInterpolationHigh;
- break;
+ case InterpolationHigh:
+ quality = kCGInterpolationHigh;
+ break;
}
CGContextSetInterpolationQuality(platformContext(), quality);
}
@@ -1055,18 +1055,18 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
CGInterpolationQuality quality = CGContextGetInterpolationQuality(platformContext());
switch (quality) {
- case kCGInterpolationDefault:
- return InterpolationDefault;
- case kCGInterpolationNone:
- return InterpolationNone;
- case kCGInterpolationLow:
- return InterpolationLow;
+ case kCGInterpolationDefault:
+ return InterpolationDefault;
+ case kCGInterpolationNone:
+ return InterpolationNone;
+ case kCGInterpolationLow:
+ return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
- case kCGInterpolationMedium:
- return InterpolationMedium;
+ case kCGInterpolationMedium:
+ return InterpolationMedium;
#endif
- case kCGInterpolationHigh:
- return InterpolationHigh;
+ case kCGInterpolationHigh:
+ return InterpolationHigh;
}
return InterpolationDefault;
}
@@ -1079,32 +1079,32 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
// Wow, wish CG had used bits here.
CGContextRef context = platformContext();
switch (mode) {
- case cTextInvisible: // Invisible
- CGContextSetTextDrawingMode(context, kCGTextInvisible);
- break;
- case cTextFill: // Fill
- CGContextSetTextDrawingMode(context, kCGTextFill);
- break;
- case cTextStroke: // Stroke
- CGContextSetTextDrawingMode(context, kCGTextStroke);
- break;
- case 3: // Fill | Stroke
- CGContextSetTextDrawingMode(context, kCGTextFillStroke);
- break;
- case cTextClip: // Clip
- CGContextSetTextDrawingMode(context, kCGTextClip);
- break;
- case 5: // Fill | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillClip);
- break;
- case 6: // Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
- break;
- case 7: // Fill | Stroke | Clip
- CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
- break;
- default:
- break;
+ case cTextInvisible: // Invisible
+ CGContextSetTextDrawingMode(context, kCGTextInvisible);
+ break;
+ case cTextFill: // Fill
+ CGContextSetTextDrawingMode(context, kCGTextFill);
+ break;
+ case cTextStroke: // Stroke
+ CGContextSetTextDrawingMode(context, kCGTextStroke);
+ break;
+ case 3: // Fill | Stroke
+ CGContextSetTextDrawingMode(context, kCGTextFillStroke);
+ break;
+ case cTextClip: // Clip
+ CGContextSetTextDrawingMode(context, kCGTextClip);
+ break;
+ case 5: // Fill | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillClip);
+ break;
+ case 6: // Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
+ break;
+ case 7: // Fill | Stroke | Clip
+ CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
+ break;
+ default:
+ break;
}
}
@@ -1138,54 +1138,54 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm.
void GraphicsContext::setCompositeOperation(CompositeOperator mode)
-{
+{
if (paintingDisabled())
return;
- CGBlendMode target = kCGBlendModeNormal;
+ CGBlendMode target = kCGBlendModeNormal;
switch (mode) {
- case CompositeClear:
- target = kCGBlendModeClear;
- break;
- case CompositeCopy:
- target = kCGBlendModeCopy;
- break;
- case CompositeSourceOver:
- //kCGBlendModeNormal
- break;
- case CompositeSourceIn:
- target = kCGBlendModeSourceIn;
- break;
- case CompositeSourceOut:
- target = kCGBlendModeSourceOut;
- break;
- case CompositeSourceAtop:
- target = kCGBlendModeSourceAtop;
- break;
- case CompositeDestinationOver:
- target = kCGBlendModeDestinationOver;
- break;
- case CompositeDestinationIn:
- target = kCGBlendModeDestinationIn;
- break;
- case CompositeDestinationOut:
- target = kCGBlendModeDestinationOut;
- break;
- case CompositeDestinationAtop:
- target = kCGBlendModeDestinationAtop;
- break;
- case CompositeXOR:
- target = kCGBlendModeXOR;
- break;
- case CompositePlusDarker:
- target = kCGBlendModePlusDarker;
- break;
- case CompositeHighlight:
- // currently unsupported
- break;
- case CompositePlusLighter:
- target = kCGBlendModePlusLighter;
- break;
+ case CompositeClear:
+ target = kCGBlendModeClear;
+ break;
+ case CompositeCopy:
+ target = kCGBlendModeCopy;
+ break;
+ case CompositeSourceOver:
+ //kCGBlendModeNormal
+ break;
+ case CompositeSourceIn:
+ target = kCGBlendModeSourceIn;
+ break;
+ case CompositeSourceOut:
+ target = kCGBlendModeSourceOut;
+ break;
+ case CompositeSourceAtop:
+ target = kCGBlendModeSourceAtop;
+ break;
+ case CompositeDestinationOver:
+ target = kCGBlendModeDestinationOver;
+ break;
+ case CompositeDestinationIn:
+ target = kCGBlendModeDestinationIn;
+ break;
+ case CompositeDestinationOut:
+ target = kCGBlendModeDestinationOut;
+ break;
+ case CompositeDestinationAtop:
+ target = kCGBlendModeDestinationAtop;
+ break;
+ case CompositeXOR:
+ target = kCGBlendModeXOR;
+ break;
+ case CompositePlusDarker:
+ target = kCGBlendModePlusDarker;
+ break;
+ case CompositeHighlight:
+ // currently unsupported
+ break;
+ case CompositePlusLighter:
+ target = kCGBlendModePlusLighter;
+ break;
}
CGContextSetBlendMode(platformContext(), target);
}
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 6db7e88..97bcba5 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -65,7 +65,9 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
bytesPerRow *= 4;
}
- m_data.m_data = tryFastCalloc(size.height(), bytesPerRow);
+ if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
+ return;
+
ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
CGColorSpaceRef colorSpace;
@@ -122,12 +124,13 @@ Image* ImageBuffer::image() const
return m_image.get();
}
-PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+template <Multiply multiplied>
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
{
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* data = result->data()->data()->data();
- if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
+ if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height())
memset(data, 0, result->data()->length());
int originx = rect.x();
@@ -137,8 +140,8 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originx = 0;
}
int endx = rect.x() + rect.width();
- if (endx > m_size.width())
- endx = m_size.width();
+ if (endx > size.width())
+ endx = size.width();
int numColumns = endx - originx;
int originy = rect.y();
@@ -148,20 +151,21 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
originy = 0;
}
int endy = rect.y() + rect.height();
- if (endy > m_size.height())
- endy = m_size.height();
+ if (endy > size.height())
+ endy = size.height();
int numRows = endy - originy;
- unsigned srcBytesPerRow = 4 * m_size.width();
+ unsigned srcBytesPerRow = 4 * size.width();
unsigned destBytesPerRow = 4 * rect.width();
// ::create ensures that all ImageBuffers have valid data, so we don't need to check it here.
- unsigned char* srcRows = reinterpret_cast<unsigned char*>(m_data.m_data) + originy * srcBytesPerRow + originx * 4;
+ unsigned char* srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
- if (unsigned char alpha = srcRows[basex + 3]) {
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha) {
destRows[basex] = (srcRows[basex] * 255) / alpha;
destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
@@ -175,7 +179,18 @@ PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
return result;
}
-void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Unmultiplied>(rect, m_data, m_size);
+}
+
+PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+{
+ return getImageData<Premultiplied>(rect, m_data, m_size);
+}
+
+template <Multiply multiplied>
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -183,36 +198,36 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
int originx = sourceRect.x();
int destx = destPoint.x() + sourceRect.x();
ASSERT(destx >= 0);
- ASSERT(destx < m_size.width());
+ ASSERT(destx < size.width());
ASSERT(originx >= 0);
ASSERT(originx <= sourceRect.right());
int endx = destPoint.x() + sourceRect.right();
- ASSERT(endx <= m_size.width());
+ ASSERT(endx <= size.width());
int numColumns = endx - destx;
int originy = sourceRect.y();
int desty = destPoint.y() + sourceRect.y();
ASSERT(desty >= 0);
- ASSERT(desty < m_size.height());
+ ASSERT(desty < size.height());
ASSERT(originy >= 0);
ASSERT(originy <= sourceRect.bottom());
int endy = destPoint.y() + sourceRect.bottom();
- ASSERT(endy <= m_size.height());
+ ASSERT(endy <= size.height());
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- unsigned destBytesPerRow = 4 * m_size.width();
+ unsigned destBytesPerRow = 4 * size.width();
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
- unsigned char* destRows = reinterpret_cast<unsigned char*>(m_data.m_data) + desty * destBytesPerRow + destx * 4;
+ unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
for (int y = 0; y < numRows; ++y) {
for (int x = 0; x < numColumns; x++) {
int basex = x * 4;
unsigned char alpha = srcRows[basex + 3];
- if (alpha != 255) {
+ if (multiplied == Unmultiplied && alpha != 255) {
destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
@@ -225,6 +240,16 @@ void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, con
}
}
+void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
+void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
+{
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
+}
+
static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType)
{
#if PLATFORM(MAC)