auto_ptr<ImageBuffer> ImageBuffer::create(const IntSize& size, bool grayScale) { if (size.width() < 0 || size.height() < 0) return auto_ptr<ImageBuffer>(); unsigned int bytesPerRow = size.width(); if (!grayScale) { // Protect against overflow if (bytesPerRow > 0x3FFFFFFF) return auto_ptr<ImageBuffer>(); bytesPerRow *= 4; } void* imageBuffer = tryFastCalloc(size.height(), bytesPerRow); if (!imageBuffer) return auto_ptr<ImageBuffer>(); CGColorSpaceRef colorSpace = grayScale ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGContextRef cgContext = CGBitmapContextCreate(imageBuffer, size.width(), size.height(), 8, bytesPerRow, colorSpace, grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); if (!cgContext) { fastFree(imageBuffer); return auto_ptr<ImageBuffer>(); } auto_ptr<GraphicsContext> context(new GraphicsContext(cgContext)); context->scale(FloatSize(1, -1)); context->translate(0, -size.height()); CGContextRelease(cgContext); return auto_ptr<ImageBuffer>(new ImageBuffer(imageBuffer, size, context)); }
ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success) : m_data(size) , m_size(size) { success = false; // Make early return mean failure. unsigned bytesPerRow; if (size.width() < 0 || size.height() < 0) return; bytesPerRow = size.width(); if (!grayScale) { // Protect against overflow if (bytesPerRow > 0x3FFFFFFF) return; bytesPerRow *= 4; } m_data.m_data = tryFastCalloc(size.height(), bytesPerRow); ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0); CGColorSpaceRef colorSpace = grayScale ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); CGContextRef cgContext = CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, colorSpace, grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(colorSpace); if (!cgContext) return; m_context.set(new GraphicsContext(cgContext)); m_context->scale(FloatSize(1, -1)); m_context->translate(0, -size.height()); CGContextRelease(cgContext); success = true; }
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; }
Signature* Signature::create(SignatureArgCount argumentCount) { // Hashing relies on allocation zero-initializing trailing elements. auto allocated = tryFastCalloc(allocatedSize(argumentCount), 1); Signature* signature; if (!allocated.getValue(signature)) return nullptr; new (signature) Signature(argumentCount); return signature; }
JSArrayBufferView::ConstructionContext::ConstructionContext( VM& vm, Structure* structure, uint32_t length, uint32_t elementSize, InitializationMode mode) : m_structure(0) , m_length(length) , m_butterfly(0) { if (length <= fastSizeLimit) { // Attempt GC allocation. void* temp = 0; size_t size = sizeOf(length, elementSize); // CopiedSpace only allows non-zero size allocations. if (size && !vm.heap.tryAllocateStorage(0, size, &temp)) return; m_structure = structure; m_vector = temp; m_mode = FastTypedArray; #if USE(JSVALUE32_64) if (mode == ZeroFill) { uint64_t* asWords = static_cast<uint64_t*>(m_vector); for (unsigned i = size / sizeof(uint64_t); i--;) asWords[i] = 0; } #endif // USE(JSVALUE32_64) return; } // Don't allow a typed array to use more than 2GB. if (length > static_cast<unsigned>(INT_MAX) / elementSize) return; if (mode == ZeroFill) { if (!tryFastCalloc(length, elementSize).getValue(m_vector)) return; } else { if (!tryFastMalloc(length * elementSize).getValue(m_vector)) return; } vm.heap.reportExtraMemoryCost(static_cast<size_t>(length) * elementSize); m_structure = structure; m_mode = OversizeTypedArray; }
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 FloatSize& size, float resolutionScale, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success) : m_logicalSize(size) , m_resolutionScale(resolutionScale) { float scaledWidth = ceilf(resolutionScale * size.width()); float scaledHeight = ceilf(resolutionScale * size.height()); // FIXME: Should we automatically use a lower resolution? if (!FloatSize(scaledWidth, scaledHeight).isExpressibleAsIntSize()) return; m_size = IntSize(scaledWidth, scaledHeight); m_data.backingStoreSize = m_size; success = false; // Make early return mean failure. bool accelerateRendering = renderingMode == Accelerated; if (m_size.width() <= 0 || m_size.height() <= 0) return; #if USE(IOSURFACE_CANVAS_BACKING_STORE) Checked<int, RecordOverflow> width = m_size.width(); Checked<int, RecordOverflow> height = m_size.height(); #endif // Prevent integer overflows m_data.bytesPerRow = 4 * Checked<unsigned, RecordOverflow>(m_data.backingStoreSize.width()); Checked<size_t, RecordOverflow> numBytes = Checked<unsigned, RecordOverflow>(m_data.backingStoreSize.height()) * m_data.bytesPerRow; if (numBytes.hasOverflowed()) return; #if USE(IOSURFACE_CANVAS_BACKING_STORE) IntSize maxSize = IOSurface::maximumSize(); if (width.unsafeGet() > maxSize.width() || height.unsafeGet() > maxSize.height()) accelerateRendering = false; #else ASSERT(renderingMode == Unaccelerated); #endif m_data.colorSpace = cachedCGColorSpace(imageColorSpace); RetainPtr<CGContextRef> cgContext; if (accelerateRendering) { #if USE(IOSURFACE_CANVAS_BACKING_STORE) FloatSize userBounds = scaleSizeToUserSpace(FloatSize(width.unsafeGet(), height.unsafeGet()), m_data.backingStoreSize, m_size); m_data.surface = IOSurface::create(m_data.backingStoreSize, IntSize(userBounds), imageColorSpace); cgContext = m_data.surface->ensurePlatformContext(); if (cgContext) CGContextClearRect(cgContext.get(), FloatRect(FloatPoint(), userBounds)); #endif if (!cgContext) accelerateRendering = false; // If allocation fails, fall back to non-accelerated path. } if (!accelerateRendering) { if (!tryFastCalloc(m_data.backingStoreSize.height(), m_data.bytesPerRow.unsafeGet()).getValue(m_data.data)) return; ASSERT(!(reinterpret_cast<intptr_t>(m_data.data) & 3)); #if USE_ARGB32 m_data.bitmapInfo = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host; #else m_data.bitmapInfo = kCGImageAlphaPremultipliedLast; #endif cgContext = adoptCF(CGBitmapContextCreate(m_data.data, m_data.backingStoreSize.width(), m_data.backingStoreSize.height(), 8, m_data.bytesPerRow.unsafeGet(), m_data.colorSpace, m_data.bitmapInfo)); // Create a live image that wraps the data. m_data.dataProvider = adoptCF(CGDataProviderCreateWithData(0, m_data.data, numBytes.unsafeGet(), releaseImageData)); if (!cgContext) return; m_data.context = std::make_unique<GraphicsContext>(cgContext.get()); } context().scale(FloatSize(1, -1)); context().translate(0, -m_data.backingStoreSize.height()); context().applyDeviceScaleFactor(m_resolutionScale); 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; }