ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success) : m_data(size) , m_size(size) , m_accelerateRendering(renderingMode == Accelerated) { #if !USE(IOSURFACE_CANVAS_BACKING_STORE) ASSERT(renderingMode == Unaccelerated); #endif success = false; // Make early return mean failure. if (size.width() < 0 || size.height() < 0) return; unsigned bytesPerRow = size.width(); if (bytesPerRow > 0x3FFFFFFF) // Protect against overflow return; bytesPerRow *= 4; m_data.m_bytesPerRow = bytesPerRow; size_t dataSize = size.height() * bytesPerRow; switch (imageColorSpace) { case ColorSpaceDeviceRGB: m_data.m_colorSpace = deviceRGBColorSpaceRef(); break; case ColorSpaceSRGB: m_data.m_colorSpace = sRGBColorSpaceRef(); break; case ColorSpaceLinearRGB: m_data.m_colorSpace = linearRGBColorSpaceRef(); break; } RetainPtr<CGContextRef> cgContext; if (!m_accelerateRendering) { if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data)) return; ASSERT(!(reinterpret_cast<size_t>(m_data.m_data) & 2)); m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast; cgContext.adoptCF(CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, m_data.m_colorSpace, m_data.m_bitmapInfo)); // Create a live image that wraps the data. m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData)); } else { #if USE(IOSURFACE_CANVAS_BACKING_STORE) m_data.m_surface = createIOSurface(size); cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), size.width(), size.height(), m_data.m_colorSpace)); #else m_accelerateRendering = false; // Force to false on older platforms #endif } if (!cgContext) return; m_context.set(new GraphicsContext(cgContext.get())); m_context->scale(FloatSize(1, -1)); m_context->translate(0, -size.height()); success = true; }
ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, DeferralMode, bool& success) : m_data(size) // NOTE: The input here isn't important as ImageBufferDataCG's constructor just ignores it. , m_size(size) { success = false; // Make early return mean failure. bool accelerateRendering = renderingMode == Accelerated; if (size.width() <= 0 || size.height() <= 0) return; Checked<int, RecordOverflow> width = size.width(); Checked<int, RecordOverflow> height = size.height(); // Prevent integer overflows m_data.m_bytesPerRow = 4 * width; Checked<size_t, RecordOverflow> numBytes = height * m_data.m_bytesPerRow; if (numBytes.hasOverflowed()) return; #if USE(IOSURFACE_CANVAS_BACKING_STORE) if (width.unsafeGet() >= maxIOSurfaceDimension || height.unsafeGet() >= maxIOSurfaceDimension || (width * height).unsafeGet() < minIOSurfaceArea) accelerateRendering = false; #else ASSERT(renderingMode == Unaccelerated); #endif switch (imageColorSpace) { case ColorSpaceDeviceRGB: m_data.m_colorSpace = deviceRGBColorSpaceRef(); break; case ColorSpaceSRGB: m_data.m_colorSpace = sRGBColorSpaceRef(); break; case ColorSpaceLinearRGB: m_data.m_colorSpace = linearRGBColorSpaceRef(); break; } RetainPtr<CGContextRef> cgContext; if (accelerateRendering) { #if USE(IOSURFACE_CANVAS_BACKING_STORE) m_data.m_surface = createIOSurface(size); cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), width.unsafeGet(), height.unsafeGet(), m_data.m_colorSpace)); #endif if (!cgContext) accelerateRendering = false; // If allocation fails, fall back to non-accelerated path. } if (!accelerateRendering) { if (!tryFastCalloc(height.unsafeGet(), m_data.m_bytesPerRow.unsafeGet()).getValue(m_data.m_data)) return; ASSERT(!(reinterpret_cast<size_t>(m_data.m_data) & 2)); m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast; cgContext.adoptCF(CGBitmapContextCreate(m_data.m_data, width.unsafeGet(), height.unsafeGet(), 8, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo)); // Create a live image that wraps the data. m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, numBytes.unsafeGet(), releaseImageData)); } if (!cgContext) return; m_context = adoptPtr(new GraphicsContext(cgContext.get())); m_context->scale(FloatSize(1, -1)); m_context->translate(0, -height.unsafeGet()); m_context->setIsAcceleratedContext(accelerateRendering); #if defined(BUILDING_ON_LION) m_data.m_lastFlushTime = currentTimeMS(); #endif success = true; }
ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success) : m_data(size) , m_size(size) , m_accelerateRendering(renderingMode == Accelerated) { success = false; // Make early return mean failure. if (size.width() <= 0 || size.height() <= 0) return; Checked<int, RecordOverflow> width = size.width(); Checked<int, RecordOverflow> height = size.height(); // Prevent integer overflows m_data.m_bytesPerRow = 4 * width; Checked<size_t, RecordOverflow> dataSize = height * m_data.m_bytesPerRow; if (dataSize.hasOverflowed()) return; #if USE(IOSURFACE_CANVAS_BACKING_STORE) if (width.unsafeGet() >= maxIOSurfaceDimension || height.unsafeGet() >= maxIOSurfaceDimension || (width * height).unsafeGet() < minIOSurfaceArea) m_accelerateRendering = false; #else ASSERT(renderingMode == Unaccelerated); #endif switch (imageColorSpace) { case ColorSpaceDeviceRGB: m_data.m_colorSpace = deviceRGBColorSpaceRef(); break; case ColorSpaceSRGB: m_data.m_colorSpace = sRGBColorSpaceRef(); break; case ColorSpaceLinearRGB: m_data.m_colorSpace = linearRGBColorSpaceRef(); break; } RetainPtr<CGContextRef> cgContext; if (m_accelerateRendering) { #if USE(IOSURFACE_CANVAS_BACKING_STORE) m_data.m_surface = createIOSurface(size); cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), width.unsafeGet(), height.unsafeGet(), m_data.m_colorSpace)); #endif if (!cgContext) m_accelerateRendering = false; // If allocation fails, fall back to non-accelerated path. } if (!m_accelerateRendering) { if (!tryFastCalloc(height.unsafeGet(), m_data.m_bytesPerRow.unsafeGet()).getValue(m_data.m_data)) return; ASSERT(!(reinterpret_cast<size_t>(m_data.m_data) & 2)); #if USE_ARGB32 m_data.m_bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; #else m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast; #endif cgContext.adoptCF(CGBitmapContextCreate(m_data.m_data, width.unsafeGet(), height.unsafeGet(), 8, m_data.m_bytesPerRow.unsafeGet(), m_data.m_colorSpace, m_data.m_bitmapInfo)); // Create a live image that wraps the data. m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize.unsafeGet(), releaseImageData)); } if (!cgContext) return; m_context= adoptPtr(new GraphicsContext(cgContext.get())); m_context->scale(FloatSize(1, -1)); m_context->translate(0, -height.unsafeGet()); success = true; }