Changeset 113457 in webkit
- Timestamp:
- Apr 6, 2012, 10:48:34 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r113456 r113457 1 2012-04-06 Dan Bernstein <mitz@apple.com> 2 3 <rdar://problem/10912476> Pixel access canvas APIs do not work transparently with high-DPI backing store 4 https://bugs.webkit.org/show_bug.cgi?id=83072 5 6 Reviewed by Simon Fraser. 7 8 Made getImageData, putImageData, and toDataURL downsample/upsample when pixels in the canvas 9 backing store are not in a 1:1 ratio to CSS pixels. This makes clients of these APIs 10 indifferent to the backing store resolution, up to sampling artifacts. 11 12 In order for this to work, ImageBuffer has to know and respect the resolutionScale 13 parameter. This change makes the Core Graphics-based implementation of ImageBuffer do this, 14 but on other platforms, resolutionScale values other than 1 will not work. Such platforms 15 should not enable the HIGH_DPI_CANVAS feature. 16 17 * html/HTMLCanvasElement.cpp: 18 (WebCore::HTMLCanvasElement::HTMLCanvasElement): Updated a comment. 19 (WebCore::HTMLCanvasElement::createImageBuffer): Changed to create an ImageBuffer with 20 the desired resolution instead of 1. 21 * html/canvas/CanvasRenderingContext2D.cpp: 22 (WebCore::CanvasRenderingContext2D::drawImage): Removed code that scaled the source rect, 23 since this is now handled at the ImageBuffer level. 24 (WebCore::CanvasRenderingContext2D::createImageData): Now returns ImageData of the requested 25 size regardless of the backing store resolution. 26 (WebCore::CanvasRenderingContext2D::getImageData): Ditto. 27 * platform/graphics/ImageBuffer.h: 28 (WebCore::ImageBuffer::create): Removed some code that tried to apply the resolution scale 29 to the buffer after creating it, and changed to pass the resolution scale down to the 30 (platform-specific) constructor, which can apply it correctly. 31 * platform/graphics/cairo/ImageBufferCairo.cpp: 32 (WebCore::ImageBuffer::ImageBuffer): 33 * platform/graphics/cg/ImageBufferCG.cpp: 34 (WebCore::ImageBuffer::ImageBuffer): Added a resolutionScale parameter, which is used to 35 compute the backing buffer size, and to apply a device scale factor to the context. 36 (WebCore::ImageBuffer::copyImage): Changed to return an image scaled down to the logical 37 size of the buffer. 38 (WebCore::ImageBuffer::getUnmultipliedImageData): Changed to pass the resolution scale to 39 ImageData::getData(). 40 (WebCore::ImageBuffer::getPremultipliedImageData): Ditto. 41 (WebCore::ImageBuffer::putByteArray): Changed to pass the resolution scale to 42 ImageData::putData(). When drawing the byte array as an image, changed to preserve the base 43 CTM in the destination context (thus mapping from image data pixels to backing store pixels). 44 (WebCore::ImageBuffer::toDataURL): Fixed a CGColorSpace leak. Made the returned image have 45 the buffer’s logical size instead of the backing buffer’s size. 46 (WebCore::ImageDataToDataURL): Fixed a CGColorSpace leak. 47 * platform/graphics/cg/ImageBufferDataCG.cpp: 48 (WebCore::ImageBufferData::getData): Added a resolutionScale parameter. The source 49 coordinates are scaled by the value of that parameter, and a reverse scaling transform 50 is applied when copying from the backing store into the destination (either explicitly 51 using Accelerate or implicitly by drawing as an image). Since after scaling, 52 unpremultiplication and component permutation are done in-place, made the 53 non-Accelerate code that does these things safe in this case. 54 (WebCore::ImageBufferData::putData): Added a resolutionScale parameter. The destination 55 coordinates are scaled by the value of that parameter, and a scaling transform is applied 56 when copying from the source into the backing store (either explicitly using Accelerate or 57 implicitly by drawing as an image). Since after scaling, premultiplication and component 58 permutation are done in-place, made the non-Accelerate code that does these things safe in 59 this case. 60 * platform/graphics/cg/ImageBufferDataCG.h: 61 * platform/graphics/qt/ImageBufferQt.cpp: 62 (WebCore::ImageBuffer::ImageBuffer): 63 * platform/graphics/skia/ImageBufferSkia.cpp: 64 (WebCore::ImageBuffer::ImageBuffer): 65 * platform/graphics/wince/ImageBufferWinCE.cpp: 66 (WebCore::ImageBuffer::ImageBuffer): 67 * platform/graphics/wx/ImageBufferWx.cpp: 68 (WebCore::ImageBuffer::ImageBuffer): 69 1 70 2012-04-06 Dana Jansens <danakj@chromium.org> 2 71 -
trunk/Source/WebCore/html/HTMLCanvasElement.cpp
r111872 r113457 86 86 , m_ignoreReset(false) 87 87 #if ENABLE(HIGH_DPI_CANVAS) 88 // FIXME: Make this the default once https://bugs.webkit.org/show_bug.cgi?id=73645 has been fixed. 88 // NOTE: High-DPI canvas requires the platform-specific ImageBuffer implementation to respect 89 // the resolutionScale parameter. 89 90 , m_deviceScaleFactor(document->frame() ? document->frame()->page()->deviceScaleFactor() : 1) 90 91 #else … … 544 545 #endif 545 546 DeferralMode deferralMode = shouldDefer() ? Deferred : NonDeferred; 546 m_imageBuffer = ImageBuffer::create( bufferSize, 1, ColorSpaceDeviceRGB, renderingMode, deferralMode);547 m_imageBuffer = ImageBuffer::create(size(), m_deviceScaleFactor, ColorSpaceDeviceRGB, renderingMode, deferralMode); 547 548 if (!m_imageBuffer) 548 549 return; 549 m_imageBuffer->context()->scale(FloatSize(bufferSize.width() / logicalSize.width(), bufferSize.height() / logicalSize.height()));550 550 m_imageBuffer->context()->setShadowsIgnoreTransforms(true); 551 551 m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality); -
trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
r112537 r113457 1354 1354 #endif 1355 1355 1356 // drawImageBuffer's srcRect is in buffer pixels (backing store pixels, in our case), dstRect is in canvas pixels.1357 FloatRect bufferSrcRect(sourceCanvas->convertLogicalToDevice(srcRect));1358 1359 1356 if (rectContainsCanvas(dstRect)) { 1360 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, bufferSrcRect, state().m_globalComposite);1357 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite); 1361 1358 didDrawEntireCanvas(); 1362 1359 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { 1363 fullCanvasCompositedDrawImage(buffer, ColorSpaceDeviceRGB, dstRect, bufferSrcRect, state().m_globalComposite);1360 fullCanvasCompositedDrawImage(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite); 1364 1361 didDrawEntireCanvas(); 1365 1362 } else if (state().m_globalComposite == CompositeCopy) { 1366 1363 clearCanvas(); 1367 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, bufferSrcRect, state().m_globalComposite);1364 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite); 1368 1365 didDrawEntireCanvas(); 1369 1366 } else { 1370 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, bufferSrcRect, state().m_globalComposite);1367 c->drawImageBuffer(buffer, ColorSpaceDeviceRGB, dstRect, srcRect, state().m_globalComposite); 1371 1368 didDraw(dstRect); 1372 1369 } … … 1779 1776 1780 1777 FloatSize logicalSize(fabs(sw), fabs(sh)); 1781 FloatSize deviceSize = canvas()->convertLogicalToDevice(logicalSize); 1782 if (!deviceSize.isExpressibleAsIntSize()) 1778 if (!logicalSize.isExpressibleAsIntSize()) 1783 1779 return 0; 1784 1780 1785 IntSize size (deviceSize.width(), deviceSize.height());1781 IntSize size = expandedIntSize(logicalSize); 1786 1782 if (size.width() < 1) 1787 1783 size.setWidth(1); … … 1819 1815 1820 1816 FloatRect logicalRect(sx, sy, sw, sh); 1821 FloatRect deviceRect = canvas()->convertLogicalToDevice(logicalRect); 1822 if (deviceRect.width() < 1) 1823 deviceRect.setWidth(1); 1824 if (deviceRect.height() < 1) 1825 deviceRect.setHeight(1); 1826 if (!deviceRect.isExpressibleAsIntRect()) 1817 if (logicalRect.width() < 1) 1818 logicalRect.setWidth(1); 1819 if (logicalRect.height() < 1) 1820 logicalRect.setHeight(1); 1821 if (!logicalRect.isExpressibleAsIntRect()) 1827 1822 return 0; 1828 1823 1829 IntRect imageDataRect (deviceRect);1824 IntRect imageDataRect = enclosingIntRect(logicalRect); 1830 1825 ImageBuffer* buffer = canvas()->buffer(); 1831 1826 if (!buffer) -
trunk/Source/WebCore/platform/graphics/ImageBuffer.h
r109016 r113457 81 81 { 82 82 bool success = false; 83 float scaledWidth = ceilf(resolutionScale * size.width()); 84 float scaledHeight = ceilf(resolutionScale * size.height()); 85 IntSize internalSize(scaledWidth, scaledHeight); 86 87 OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(internalSize, colorSpace, renderingMode, deferralMode, success)); 83 OwnPtr<ImageBuffer> buf = adoptPtr(new ImageBuffer(size, resolutionScale, colorSpace, renderingMode, deferralMode, success)); 88 84 if (!success) 89 85 return nullptr; 90 91 buf->m_logicalSize = size;92 buf->m_resolutionScale = resolutionScale;93 buf->context()->scale(FloatSize(resolutionScale, resolutionScale));94 86 return buf.release(); 95 87 } … … 154 146 // This constructor will place its success into the given out-variable 155 147 // so that create() knows when it should return failure. 156 ImageBuffer(const IntSize&, ColorSpace, RenderingMode, DeferralMode, bool& success);148 ImageBuffer(const IntSize&, float resolutionScale, ColorSpace, RenderingMode, DeferralMode, bool& success); 157 149 }; 158 150 -
trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
r109016 r113457 55 55 } 56 56 57 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)57 ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) 58 58 : m_data(size) 59 59 , m_size(size) 60 , m_logicalSize(size) 60 61 { 61 62 success = false; // Make early return mean error. -
trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
r109016 r113457 108 108 } 109 109 110 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success)110 ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success) 111 111 : m_data(size) // NOTE: The input here isn't important as ImageBufferDataCG's constructor just ignores it. 112 , m_size(size) 113 { 112 , m_logicalSize(size) 113 , m_resolutionScale(resolutionScale) 114 { 115 float scaledWidth = ceilf(resolutionScale * size.width()); 116 float scaledHeight = ceilf(resolutionScale * size.height()); 117 118 // FIXME: Should we automatically use a lower resolution? 119 if (!FloatSize(scaledWidth, scaledHeight).isExpressibleAsIntSize()) 120 return; 121 122 m_size = IntSize(scaledWidth, scaledHeight); 123 114 124 success = false; // Make early return mean failure. 115 125 bool accelerateRendering = renderingMode == Accelerated; 116 if ( size.width() <= 0 ||size.height() <= 0)126 if (m_size.width() <= 0 || m_size.height() <= 0) 117 127 return; 118 128 119 Checked<int, RecordOverflow> width = size.width();120 Checked<int, RecordOverflow> height = size.height();129 Checked<int, RecordOverflow> width = m_size.width(); 130 Checked<int, RecordOverflow> height = m_size.height(); 121 131 122 132 // Prevent integer overflows … … 148 158 if (accelerateRendering) { 149 159 #if USE(IOSURFACE_CANVAS_BACKING_STORE) 150 m_data.m_surface = createIOSurface( size);160 m_data.m_surface = createIOSurface(m_size); 151 161 cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), width.unsafeGet(), height.unsafeGet(), m_data.m_colorSpace)); 152 162 #endif … … 170 180 171 181 m_context = adoptPtr(new GraphicsContext(cgContext.get())); 182 m_context->applyDeviceScaleFactor(m_resolutionScale); 172 183 m_context->scale(FloatSize(1, -1)); 173 m_context->translate(0, - height.unsafeGet());184 m_context->translate(0, -size.height()); 174 185 m_context->setIsAcceleratedContext(accelerateRendering); 175 186 #if defined(BUILDING_ON_LION) … … 204 215 PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const 205 216 { 206 RetainPtr<CGImageRef> image = copyNativeImage(copyBehavior); 217 RetainPtr<CGImageRef> image; 218 if (m_resolutionScale == 1) 219 image = copyNativeImage(copyBehavior); 220 else { 221 image.adoptCF(copyNativeImage(DontCopyBackingStore)); 222 RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); 223 CGContextSetBlendMode(context.get(), kCGBlendModeCopy); 224 CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get()); 225 image = CGBitmapContextCreateImage(context.get()); 226 } 207 227 208 228 if (!image) … … 295 315 #endif 296 316 } 297 return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true );317 return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true, m_resolutionScale); 298 318 } 299 319 … … 306 326 #endif 307 327 } 308 return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false );328 return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false, m_resolutionScale); 309 329 } 310 330 … … 312 332 { 313 333 if (!m_context->isAcceleratedContext()) { 314 m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied );334 m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied, m_resolutionScale); 315 335 return; 316 336 } … … 323 343 return; 324 344 325 sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied );345 sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->internalSize(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied, 1); 326 346 327 347 // Set up context for using drawImage as a direct bit copy 328 348 CGContextRef destContext = context()->platformContext(); 329 349 CGContextSaveGState(destContext); 330 CGContextConcatCTM(destContext, AffineTransform( CGContextGetCTM(destContext)).inverse());350 CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse()); 331 351 wkCGContextResetClip(destContext); 332 352 CGContextSetInterpolationQuality(destContext, kCGInterpolationNone); … … 336 356 337 357 // Draw the image in CG coordinate space 338 IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), internalSize().height() - (destPoint.y()+sourceRect.y()) - sourceRect.height());358 IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), logicalSize().height() - (destPoint.y()+sourceRect.y()) - sourceRect.height()); 339 359 IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize); 340 360 RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage()); … … 421 441 if (CFEqual(uti.get(), jpegUTI())) { 422 442 // JPEGs don't have an alpha channel, so we have to manually composite on top of black. 423 arr = getPremultipliedImageData(IntRect(IntPoint(0, 0), internalSize()));443 arr = getPremultipliedImageData(IntRect(IntPoint(0, 0), logicalSize())); 424 444 425 445 unsigned char *data = arr->data(); 426 for (int i = 0; i < internalSize().width() * internalSize().height(); i++)446 for (int i = 0; i < logicalSize().width() * logicalSize().height(); i++) 427 447 data[i * 4 + 3] = 255; // The image is already premultiplied, so we just need to make it opaque. 428 448 429 449 RetainPtr<CGDataProviderRef> dataProvider; 430 450 431 dataProvider.adoptCF(CGDataProviderCreateWithData(0, data, 4 * internalSize().width() * internalSize().height(), 0));451 dataProvider.adoptCF(CGDataProviderCreateWithData(0, data, 4 * logicalSize().width() * logicalSize().height(), 0)); 432 452 433 453 if (!dataProvider) 434 454 return "data:,"; 435 455 436 image.adoptCF(CGImageCreate( internalSize().width(), internalSize().height(), 8, 32, 4 * internalSize().width(),437 CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,456 image.adoptCF(CGImageCreate(logicalSize().width(), logicalSize().height(), 8, 32, 4 * logicalSize().width(), 457 deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaLast, 438 458 dataProvider.get(), 0, false, kCGRenderingIntentDefault)); 439 } else 459 } else if (m_resolutionScale == 1) 440 460 image.adoptCF(copyNativeImage(CopyBackingStore)); 461 else { 462 image.adoptCF(copyNativeImage(DontCopyBackingStore)); 463 RetainPtr<CGContextRef> context(AdoptCF, CGBitmapContextCreate(0, logicalSize().width(), logicalSize().height(), 8, 4 * logicalSize().width(), deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedLast)); 464 CGContextSetBlendMode(context.get(), kCGBlendModeCopy); 465 CGContextDrawImage(context.get(), CGRectMake(0, 0, logicalSize().width(), logicalSize().height()), image.get()); 466 image.adoptCF(CGBitmapContextCreateImage(context.get())); 467 } 441 468 442 469 if (!image) … … 487 514 488 515 image.adoptCF(CGImageCreate(source.width(), source.height(), 8, 32, 4 * source.width(), 489 CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault | kCGImageAlphaLast,516 deviceRGBColorSpaceRef(), kCGBitmapByteOrderDefault | kCGImageAlphaLast, 490 517 dataProvider.get(), 0, false, kCGRenderingIntentDefault)); 491 518 -
trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.cpp
r100667 r113457 27 27 #include "ImageBufferData.h" 28 28 29 #include <CoreGraphics/CoreGraphics.h> 29 30 #include <wtf/Assertions.h> 30 31 … … 37 38 #include <dispatch/dispatch.h> 38 39 #endif 40 41 using namespace std; 39 42 40 43 #if USE(ACCELERATE) … … 114 117 #endif // USE(ACCELERATE) 115 118 116 PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied ) const119 PassRefPtr<ByteArray> ImageBufferData::getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const 117 120 { 118 121 float area = 4.0f * rect.width() * rect.height(); … … 123 126 unsigned char* data = result->data(); 124 127 125 if (rect.x() < 0 || rect.y() < 0 || rect.maxX() > size.width() || rect.maxY() > size.height()) 128 int endx = ceilf(rect.maxX() * resolutionScale); 129 int endy = ceilf(rect.maxY() * resolutionScale); 130 if (rect.x() < 0 || rect.y() < 0 || endx > size.width() || endy > size.height()) 126 131 memset(data, 0, result->length()); 127 132 128 133 int originx = rect.x(); 129 134 int destx = 0; 135 int destw = rect.width(); 130 136 if (originx < 0) { 137 destw += originx; 131 138 destx = -originx; 132 139 originx = 0; 133 140 } 134 int endx = rect.maxX(); 141 destw = min<int>(destw, ceilf(size.width() / resolutionScale) - originx); 142 originx *= resolutionScale; 135 143 if (endx > size.width()) 136 144 endx = size.width(); … … 139 147 int originy = rect.y(); 140 148 int desty = 0; 149 int desth = rect.height(); 141 150 if (originy < 0) { 151 desth += originy; 142 152 desty = -originy; 143 153 originy = 0; 144 154 } 145 int endy = rect.maxY(); 155 desth = min<int>(desth, ceilf(size.height() / resolutionScale) - originy); 156 originy *= resolutionScale; 146 157 if (endy > size.height()) 147 158 endy = size.height(); … … 170 181 171 182 vImage_Buffer dst; 172 dst.height = height;173 dst.width = width;183 dst.height = desth; 184 dst.width = destw; 174 185 dst.rowBytes = destBytesPerRow; 175 186 dst.data = destRows; 176 187 188 if (resolutionScale != 1) { 189 vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. 190 Pixel_8888 backgroundColor; 191 vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); 192 // The unpremultiplying will be done in-place. 193 src = dst; 194 } 195 177 196 vImageUnpremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); 178 197 return result.release(); 179 198 } 180 199 #endif 200 if (resolutionScale != 1) { 201 RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 202 RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); 203 RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 204 CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); 205 CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. 206 if (!unmultiplied) 207 return result.release(); 208 209 srcRows = destRows; 210 srcBytesPerRow = destBytesPerRow; 211 width = destw; 212 height = desth; 213 } 181 214 if (unmultiplied) { 182 215 for (int y = 0; y < height; ++y) { … … 211 244 212 245 #if USE(ACCELERATE) 246 vImage_Buffer src; 247 src.height = height; 248 src.width = width; 249 src.rowBytes = srcBytesPerRow; 250 src.data = srcRows; 251 252 vImage_Buffer dest; 253 dest.height = desth; 254 dest.width = destw; 255 dest.rowBytes = destBytesPerRow; 256 dest.data = destRows; 257 258 if (resolutionScale != 1) { 259 vImage_AffineTransform scaleTransform = { 1 / resolutionScale, 0, 0, 1 / resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. 260 Pixel_8888 backgroundColor; 261 vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); 262 // The unpremultiplying and channel-swapping will be done in-place. 263 if (unmultiplied) { 264 srcRows = destRows; 265 width = destw; 266 height = desth; 267 srcBytesPerRow = destBytesPerRow; 268 } else 269 src = dest; 270 } 271 213 272 if (unmultiplied) { 214 273 ScanlineData scanlineData; … … 221 280 dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, unpremultitplyScanline); 222 281 } else { 223 vImage_Buffer src;224 src.height = height;225 src.width = width;226 src.rowBytes = srcBytesPerRow;227 src.data = srcRows;228 229 vImage_Buffer dest;230 dest.height = height;231 dest.width = width;232 dest.rowBytes = destBytesPerRow;233 dest.data = destRows;234 235 282 // Swap pixel channels from BGRA to RGBA. 236 283 const uint8_t map[4] = { 2, 1, 0, 3 }; … … 238 285 } 239 286 #else 287 if (resolutionScale != 1) { 288 RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 289 RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); 290 RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 291 CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); 292 CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. 293 294 srcRows = destRows; 295 srcBytesPerRow = destBytesPerRow; 296 width = destw; 297 height = desth; 298 } 299 240 300 if (unmultiplied) { 241 301 for (int y = 0; y < height; ++y) { 242 302 for (int x = 0; x < width; x++) { 243 303 int basex = x * 4; 304 unsigned char b = srcRows[basex]; 244 305 unsigned char alpha = srcRows[basex + 3]; 245 306 if (alpha) { 246 307 destRows[basex] = (srcRows[basex + 2] * 255) / alpha; 247 308 destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha; 248 destRows[basex + 2] = ( srcRows[basex]* 255) / alpha;309 destRows[basex + 2] = (b * 255) / alpha; 249 310 destRows[basex + 3] = alpha; 250 311 } else { 251 312 destRows[basex] = srcRows[basex + 2]; 252 313 destRows[basex + 1] = srcRows[basex + 1]; 253 destRows[basex + 2] = srcRows[basex];314 destRows[basex + 2] = b; 254 315 destRows[basex + 3] = srcRows[basex + 3]; 255 316 } … … 262 323 for (int x = 0; x < width; x++) { 263 324 int basex = x * 4; 325 unsigned char b = srcRows[basex]; 264 326 destRows[basex] = srcRows[basex + 2]; 265 327 destRows[basex + 1] = srcRows[basex + 1]; 266 destRows[basex + 2] = srcRows[basex];328 destRows[basex + 2] = b; 267 329 destRows[basex + 3] = srcRows[basex + 3]; 268 330 } … … 281 343 } 282 344 283 void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied )345 void ImageBufferData::putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) 284 346 { 285 347 ASSERT(sourceRect.width() > 0); … … 287 349 288 350 int originx = sourceRect.x(); 289 int destx = destPoint.x() + sourceRect.x();351 int destx = (destPoint.x() + sourceRect.x()) * resolutionScale; 290 352 ASSERT(destx >= 0); 291 353 ASSERT(destx < size.width()); … … 293 355 ASSERT(originx <= sourceRect.maxX()); 294 356 295 int endx = destPoint.x() + sourceRect.maxX();357 int endx = (destPoint.x() + sourceRect.maxX()) * resolutionScale; 296 358 ASSERT(endx <= size.width()); 297 359 298 int width = endx - destx; 299 360 int width = sourceRect.width(); 361 int destw = endx - destx; 362 300 363 int originy = sourceRect.y(); 301 int desty = destPoint.y() + sourceRect.y();364 int desty = (destPoint.y() + sourceRect.y()) * resolutionScale; 302 365 ASSERT(desty >= 0); 303 366 ASSERT(desty < size.height()); … … 305 368 ASSERT(originy <= sourceRect.maxY()); 306 369 307 int endy = destPoint.y() + sourceRect.maxY();370 int endy = (destPoint.y() + sourceRect.maxY()) * resolutionScale; 308 371 ASSERT(endy <= size.height()); 309 int height = endy - desty; 372 373 int height = sourceRect.height(); 374 int desth = endy - desty; 310 375 311 376 if (width <= 0 || height <= 0) … … 330 395 331 396 vImage_Buffer dst; 332 dst.height = height;333 dst.width = width;397 dst.height = desth; 398 dst.width = destw; 334 399 dst.rowBytes = destBytesPerRow; 335 400 dst.data = destRows; 336 401 402 if (resolutionScale != 1) { 403 vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. 404 Pixel_8888 backgroundColor; 405 vImageAffineWarp_ARGB8888(&src, &dst, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); 406 // The premultiplying will be done in-place. 407 src = dst; 408 } 409 337 410 vImagePremultiplyData_RGBA8888(&src, &dst, kvImageNoFlags); 338 411 return; 339 412 } 340 413 #endif 414 if (resolutionScale != 1) { 415 RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 416 RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); 417 RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 418 CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); 419 CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. 420 if (!unmultiplied) 421 return; 422 423 srcRows = destRows; 424 srcBytesPerRow = destBytesPerRow; 425 width = destw; 426 height = desth; 427 } 428 341 429 for (int y = 0; y < height; ++y) { 342 430 for (int x = 0; x < width; x++) { … … 362 450 363 451 #if USE(ACCELERATE) 452 vImage_Buffer src; 453 src.height = height; 454 src.width = width; 455 src.rowBytes = srcBytesPerRow; 456 src.data = srcRows; 457 458 vImage_Buffer dest; 459 dest.height = desth; 460 dest.width = destw; 461 dest.rowBytes = destBytesPerRow; 462 dest.data = destRows; 463 464 if (resolutionScale != 1) { 465 vImage_AffineTransform scaleTransform = { resolutionScale, 0, 0, resolutionScale, 0, 0 }; // FIXME: Add subpixel translation. 466 Pixel_8888 backgroundColor; 467 vImageAffineWarp_ARGB8888(&src, &dest, 0, &scaleTransform, backgroundColor, kvImageEdgeExtend); 468 // The unpremultiplying and channel-swapping will be done in-place. 469 if (unmultiplied) { 470 srcRows = destRows; 471 width = destw; 472 height = desth; 473 srcBytesPerRow = destBytesPerRow; 474 } else 475 src = dest; 476 } 477 364 478 if (unmultiplied) { 365 479 ScanlineData scanlineData; … … 372 486 dispatch_apply_f(height, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &scanlineData, premultitplyScanline); 373 487 } else { 374 vImage_Buffer src;375 src.height = height;376 src.width = width;377 src.rowBytes = srcBytesPerRow;378 src.data = srcRows;379 380 vImage_Buffer dest;381 dest.height = height;382 dest.width = width;383 dest.rowBytes = destBytesPerRow;384 dest.data = destRows;385 386 488 // Swap pixel channels from RGBA to BGRA. 387 489 const uint8_t map[4] = { 2, 1, 0, 3 }; … … 389 491 } 390 492 #else 493 if (resolutionScale != 1) { 494 RetainPtr<CGContextRef> sourceContext(AdoptCF, CGBitmapContextCreate(srcRows, width, height, 8, srcBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 495 RetainPtr<CGImageRef> sourceImage(AdoptCF, CGBitmapContextCreateImage(sourceContext.get())); 496 RetainPtr<CGContextRef> destinationContext(AdoptCF, CGBitmapContextCreate(destRows, destw, desth, 8, destBytesPerRow, m_colorSpace, kCGImageAlphaPremultipliedLast)); 497 CGContextSetBlendMode(destinationContext.get(), kCGBlendModeCopy); 498 CGContextDrawImage(destinationContext.get(), CGRectMake(0, 0, width / resolutionScale, height / resolutionScale), sourceImage.get()); // FIXME: Add subpixel translation. 499 500 srcRows = destRows; 501 srcBytesPerRow = destBytesPerRow; 502 width = destw; 503 height = desth; 504 } 505 391 506 for (int y = 0; y < height; ++y) { 392 507 for (int x = 0; x < width; x++) { 393 508 int basex = x * 4; 509 unsigned char b = srcRows[basex]; 394 510 unsigned char alpha = srcRows[basex + 3]; 395 511 if (unmultiplied && alpha != 255) { 396 512 destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255; 397 513 destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255; 398 destRows[basex + 2] = ( srcRows[basex]* alpha + 254) / 255;514 destRows[basex + 2] = (b * alpha + 254) / 255; 399 515 destRows[basex + 3] = alpha; 400 516 } else { 401 517 destRows[basex] = srcRows[basex + 2]; 402 518 destRows[basex + 1] = srcRows[basex + 1]; 403 destRows[basex + 2] = srcRows[basex];519 destRows[basex + 2] = b; 404 520 destRows[basex + 3] = alpha; 405 521 } -
trunk/Source/WebCore/platform/graphics/cg/ImageBufferDataCG.h
r106278 r113457 59 59 #endif 60 60 61 PassRefPtr<ByteArray> getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied ) const;62 void putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied );61 PassRefPtr<ByteArray> getData(const IntRect& rect, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale) const; 62 void putData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, const IntSize& size, bool accelerateRendering, bool unmultiplied, float resolutionScale); 63 63 }; 64 64 -
trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
r109016 r113457 95 95 } 96 96 97 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, DeferralMode, bool& success)97 ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) 98 98 : m_data(size) 99 99 , m_size(size) 100 , m_logicalSize(size) 100 101 { 101 102 success = m_data.m_painter && m_data.m_painter->isActive(); -
trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
r112343 r113457 125 125 } 126 126 127 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode renderingMode, DeferralMode deferralMode, bool& success)127 ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode renderingMode, DeferralMode deferralMode, bool& success) 128 128 : m_data(size) 129 129 , m_size(size) 130 , m_logicalSize(size) 130 131 , m_resolutionScale(1) 131 132 { -
trunk/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
r112680 r113457 72 72 } 73 73 74 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)74 ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success) 75 75 : m_data(size) 76 76 , m_size(size) 77 { 77 , m_logicalSize(size) 78 { 79 // FIXME: Respect resoutionScale to support high-DPI canvas. 80 UNUSED_PARAM(resolutionScale); 78 81 // FIXME: colorSpace is not used 79 82 UNUSED_PARAM(colorSpace); -
trunk/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp
r112670 r113457 96 96 } 97 97 98 ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success)98 ImageBuffer::ImageBuffer(const IntSize& size, float resolutionScale, ColorSpace colorSpace, RenderingMode, DeferralMode, bool& success) 99 99 : m_data(size) 100 100 , m_size(size) 101 , m_logicalSize(size) 101 102 { 103 // FIXME: Respect resoutionScale to support high-DPI canvas. 104 UNUSED_PARAM(resolutionScale); 102 105 // FIXME: colorSpace is not used 103 106 UNUSED_PARAM(colorSpace);
Note:
See TracChangeset
for help on using the changeset viewer.