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);
}
Example #2
0
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);
}
Example #5
0
//-----------------------------------------------------------------------------
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);
}
Example #8
0
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();
}
Example #9
0
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);
}