CGPatternRef Pattern::createPlatformPattern(const AffineTransform& userSpaceTransformation) const { IntRect tileRect = tileImage()->rect(); AffineTransform patternTransform = userSpaceTransformation * m_patternSpaceTransformation; patternTransform.scaleNonUniform(1, -1); patternTransform.translate(0, -tileRect.height()); // If we're repeating in both directions, we can use image-backed patterns // instead of custom patterns, and avoid tiling-edge pixel cracks. if (m_repeatX && m_repeatY) return wkCGPatternCreateWithImageAndTransform(tileImage()->getCGImageRef(), patternTransform, wkPatternTilingConstantSpacing); // If FLT_MAX should also be used for xStep or yStep, nothing is rendered. Using fractions of FLT_MAX also // result in nothing being rendered. // INT_MAX is almost correct, but there seems to be some number wrapping occurring making the fill // pattern is not filled correctly. // To make error of floating point less than 0.5, we use the half of the number of mantissa of float (1 << 22). CGFloat xStep = m_repeatX ? tileRect.width() : (1 << 22); CGFloat yStep = m_repeatY ? tileRect.height() : (1 << 22); // The pattern will release the CGImageRef when it's done rendering in patternReleaseCallback CGImageRef platformImage = CGImageRetain(tileImage()->getCGImageRef()); const CGPatternCallbacks patternCallbacks = { 0, patternCallback, patternReleaseCallback }; return CGPatternCreate(platformImage, tileRect, patternTransform, xStep, yStep, kCGPatternTilingConstantSpacing, TRUE, &patternCallbacks); }
CGImageRef UIMachineView::vmContentImage() { if (!m_pauseShot.isNull()) { CGImageRef pauseImg = ::darwinToCGImageRef(&m_pauseShot); /* Use the pause image as background */ return pauseImg; } else { # ifdef VBOX_GUI_USE_QUARTZ2D if (vboxGlobal().vmRenderMode() == VBoxDefs::Quartz2DMode) { /* If the render mode is Quartz2D we could use the CGImageRef * of the framebuffer for the dock icon creation. This saves * some conversion time. */ CGImageRef image = static_cast<UIFrameBufferQuartz2D*>(m_pFrameBuffer)->imageRef(); CGImageRetain(image); /* Retain it, cause the consumer will release it. */ return image; } else # endif /* VBOX_GUI_USE_QUARTZ2D */ /* In image mode we have to create the image ref out of the * framebuffer */ return frameBuffertoCGImageRef(m_pFrameBuffer); } return 0; }
TemporaryRef<DataSourceSurface> SourceSurfaceCG::GetDataSurface() { //XXX: we should be more disciplined about who takes a reference and where CGImageRetain(mImage); RefPtr<DataSourceSurfaceCG> dataSurf = new DataSourceSurfaceCG(mImage); return dataSurf; }
TemporaryRef<DataSourceSurface> SourceSurfaceCG::GetDataSurface() { //XXX: we should be more disciplined about who takes a reference and where CGImageRetain(mImage); RefPtr<DataSourceSurface> dataSurf = new DataSourceSurfaceCG(mImage); // We also need to make sure that the returned surface has // surface->GetType() == SurfaceType::DATA. return new DataSourceSurfaceWrapper(dataSurf); }
//----------------------------------------------------------------------------- CGBitmap::CGBitmap (CGImageRef image) : image (image) , imageSource (0) , layer (0) , bits (0) , dirty (false) , bytesPerRow (0) { CGImageRetain (image); size.x = CGImageGetWidth (image); size.y = CGImageGetHeight (image); }
PassNativeImagePtr BitmapImage::copyUnscaledFrameAtIndex(size_t index) { if (index >= frameCount()) return nullptr; if (index >= m_frames.size() || !m_frames[index].m_frame) cacheFrame(index, 0); if (!m_frames[index].m_subsamplingLevel) return CGImageRetain(m_frames[index].m_frame); return m_source.createFrameAtIndex(index); }
void CGImageLuminanceSource::init (CGImageRef cgimage, int left, int top, int width, int height) { data_ = 0; image_ = cgimage; left_ = left; top_ = top; width_ = width; height_ = height; dataWidth_ = (int)CGImageGetWidth(image_); dataHeight_ = (int)CGImageGetHeight(image_); if (left_ + width_ > dataWidth_ || top_ + height_ > dataHeight_ || top_ < 0 || left_ < 0) { throw IllegalArgumentException("Crop rectangle does not fit within image data."); } CGColorSpaceRef space = CGImageGetColorSpace(image_); CGColorSpaceModel model = CGColorSpaceGetModel(space); if (model != kCGColorSpaceModelMonochrome || CGImageGetBitsPerComponent(image_) != 8 || CGImageGetBitsPerPixel(image_) != 8) { CGColorSpaceRef gray = CGColorSpaceCreateDeviceGray(); CGContextRef ctx = CGBitmapContextCreate(0, width, height, 8, width, gray, kCGImageAlphaNone); CGColorSpaceRelease(gray); if (top || left) { CGContextClipToRect(ctx, CGRectMake(0, 0, width, height)); } CGContextDrawImage(ctx, CGRectMake(-left, -top, width, height), image_); image_ = CGBitmapContextCreateImage(ctx); bytesPerRow_ = width; top_ = 0; left_ = 0; dataWidth_ = width; dataHeight_ = height; CGContextRelease(ctx); } else { CGImageRetain(image_); } CGDataProviderRef provider = CGImageGetDataProvider(image_); data_ = CGDataProviderCopyData(provider); }
BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer) : Image(observer) , m_currentFrame(0) , m_frames(0) , m_repetitionCount(cAnimationNone) , m_repetitionCountStatus(Unknown) , m_repetitionsComplete(0) , m_decodedSize(0) , m_decodedPropertiesSize(0) , m_frameCount(1) , m_isSolidColor(false) , m_checkedForSolidColor(false) , m_animationFinished(true) , m_allDataReceived(true) , m_haveSize(true) , m_sizeAvailable(true) , m_haveFrameCount(true) { CGFloat width = CGImageGetWidth(cgImage); CGFloat height = CGImageGetHeight(cgImage); m_decodedSize = width * height * 4; m_size = IntSize(width, height); // Since we don't have a decoder, we can't figure out the image orientation. // Set m_sizeRespectingOrientation to be the same as m_size so it's not 0x0. m_sizeRespectingOrientation = IntSize(width, height); #if PLATFORM(IOS) m_originalSize = IntSize(width, height); m_originalSizeRespectingOrientation = IntSize(width, height); #endif m_frames.grow(1); m_frames[0].m_frame = CGImageRetain(cgImage); m_frames[0].m_hasAlpha = true; m_frames[0].m_haveMetadata = true; #if PLATFORM(IOS) m_frames[0].m_scale = 1; #endif checkForSolidColor(); }
void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode) { if (!nativeImageForCurrentFrame()) return; if (!patternTransform.isInvertible()) return; CGContextRef context = ctxt->platformContext(); GraphicsContextStateSaver stateSaver(*ctxt); CGContextClipToRect(context, destRect); ctxt->setCompositeOperation(op, blendMode); CGContextTranslateCTM(context, destRect.x(), destRect.y() + destRect.height()); CGContextScaleCTM(context, 1, -1); // Compute the scaled tile size. float scaledTileHeight = tileRect.height() * narrowPrecisionToFloat(patternTransform.d()); // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being // the origin). float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out. float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight); CGImageRef tileImage = nativeImageForCurrentFrame(); float h = CGImageGetHeight(tileImage); RetainPtr<CGImageRef> subImage; if (tileRect.size() == size()) subImage = tileImage; else { // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen // because sub-images are only used for border-image, which only renders when the image is fully decoded. ASSERT(h == height()); subImage = adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect)); } // Adjust the color space. subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace); // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that // its buffer is the same size as the overall image. Because a partially decoded CGImageRef with a smaller width or height than the // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case. // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors. Snow Leopard is ok. float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a()); float w = CGImageGetWidth(tileImage); if (w == size().width() && h == size().height() && !spaceSize().width() && !spaceSize().height()) CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get()); else { // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image. static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, patternReleaseCallback }; CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY); matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context)); // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top. matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h); #if PLATFORM(IOS) matrix = CGAffineTransformScale(matrix, 1, -1); matrix = CGAffineTransformTranslate(matrix, 0, -h); #endif CGImageRef platformImage = CGImageRetain(subImage.get()); RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(platformImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()), matrix, tileRect.width() + spaceSize().width() * (1 / narrowPrecisionToFloat(patternTransform.a())), tileRect.height() + spaceSize().height() * (1 / narrowPrecisionToFloat(patternTransform.d())), kCGPatternTilingConstantSpacing, true, &patternCallbacks)); if (!pattern) return; RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0)); CGFloat alpha = 1; RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha)); CGContextSetFillColorSpace(context, patternSpace.get()); // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy). wkSetBaseCTM(context, CGAffineTransformIdentity); CGContextSetPatternPhase(context, CGSizeZero); CGContextSetFillColorWithColor(context, color.get()); CGContextFillRect(context, CGContextGetClipBoundingBox(context)); } stateSaver.restore(); if (imageObserver()) imageObserver()->didDraw(this); }