Пример #1
0
InterpolationQuality GraphicsContext::imageInterpolationQuality() const
{
    if (paintingDisabled())
        return InterpolationDefault;

    CGInterpolationQuality quality = CGContextGetInterpolationQuality(platformContext());
    switch (quality) {
    case kCGInterpolationDefault:
        return InterpolationDefault;
    case kCGInterpolationNone:
        return InterpolationNone;
    case kCGInterpolationLow:
        return InterpolationLow;
#if HAVE(CG_INTERPOLATION_MEDIUM)
    // kCGInterpolationMedium is known to be present in the CGInterpolationQuality enum.
    case kCGInterpolationMedium:
#if USE(CG_INTERPOLATION_MEDIUM)
        // Only map to InterpolationMedium if targeting a system that understands it.
        return InterpolationMedium;
#else
        return InterpolationDefault;
#endif  // USE(CG_INTERPOLATION_MEDIUM)
#endif  // HAVE(CG_INTERPOLATION_MEDIUM)
    case kCGInterpolationHigh:
        return InterpolationHigh;
    }
    return InterpolationDefault;
}
Пример #2
0
bool GiCanvasIos::drawCachedBitmap2(const GiCanvas* p, float x, float y, bool secondBmp)
{
    bool ret = false;
    
    if (p && p->getCanvasType() == getCanvasType()) {
        GiCanvasIos* gs = (GiCanvasIos*)p;
        int index = secondBmp ? 1 : 0;
        CGImageRef image = gs->m_draw->_cacheserr[index] ? NULL : gs->m_draw->_caches[index];
        CGContextRef context = m_draw->getContext();
        
        if (context && image) {
            CGRect rect = CGRectMake(x, y, m_draw->width(), m_draw->height());
            CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height());
            
            CGContextConcatCTM(context, af);
            
            CGInterpolationQuality oldQuality = CGContextGetInterpolationQuality(context);
            CGContextSetInterpolationQuality(context, kCGInterpolationNone);
            CGContextDrawImage(context, rect, image);
            CGContextSetInterpolationQuality(context, oldQuality);
            
            CGContextConcatCTM(context, CGAffineTransformInvert(af));
            ret = true;
        }
    }
    
    return ret;
}
Пример #3
0
void GiCanvasIos::endPaint(bool draw)
{
    if (m_draw->getContext())
    {
        if (draw && m_draw->_buffctx && m_draw->_context) {
            CGContextRef context = m_draw->_context;
            CGImageRef image = CGBitmapContextCreateImage(m_draw->_buffctx);
            CGRect rect = CGRectMake(0, 0, m_draw->width(), m_draw->height()); // 逻辑宽高点数
            
            if (image) {
                CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height());
                CGContextConcatCTM(context, af);    // 图像是朝上的,上下文坐标系朝下,上下颠倒显示
                
                CGInterpolationQuality old = CGContextGetInterpolationQuality(context);
                CGContextSetInterpolationQuality(context, kCGInterpolationNone);
                CGContextDrawImage(context, rect, image);
                CGContextSetInterpolationQuality(context, old);
                
                CGContextConcatCTM(context, CGAffineTransformInvert(af));   // 恢复成坐标系朝下
                CGImageRelease(image);
            }
        }
        if (m_draw->_buffctx) {
            CGContextRelease(m_draw->_buffctx);
            m_draw->_buffctx = NULL;
        }
        m_draw->_context = NULL;
        if (owner())
            owner()->_endPaint();
    }
}
Пример #4
0
bool GiCanvasIos::drawCachedBitmap(float x, float y, bool secondBmp)
{
    int index = secondBmp ? 1 : 0;
    CGImageRef image = m_draw->_cacheserr[index] ? NULL : m_draw->_caches[index];
    CGContextRef context = m_draw->getContext();
    bool ret = false;
    
    if (context && image) {
        CGRect rect = CGRectMake(x, y, m_draw->width(), m_draw->height());
        CGAffineTransform af = CGAffineTransformMake(1, 0, 0, -1, 0, m_draw->height());
        
        CGContextConcatCTM(context, af);    // 图像是朝上的,上下文坐标系朝下,上下颠倒显示
        
        CGInterpolationQuality oldQuality = CGContextGetInterpolationQuality(context);
        CGContextSetInterpolationQuality(context, kCGInterpolationNone);
        CGContextDrawImage(context, rect, image);
        CGContextSetInterpolationQuality(context, oldQuality);
        
        CGContextConcatCTM(context, CGAffineTransformInvert(af));   // 恢复成坐标系朝下
        ret = true;
    }
    
    return ret;
}
Пример #5
0
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator compositeOp)
{
    startAnimation();

    RetainPtr<CGImageRef> image = frameAtIndex(m_currentFrame);
    if (!image) // If it's too early we won't have an image yet.
        return;
    
    if (mayFillWithSolidColor()) {
        fillWithSolidColor(ctxt, destRect, solidColor(), styleColorSpace, compositeOp);
        return;
    }

    float currHeight = CGImageGetHeight(image.get());
    if (currHeight <= srcRect.y())
        return;

    CGContextRef context = ctxt->platformContext();
    ctxt->save();

    bool shouldUseSubimage = false;

    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
    // and then set a clip to the portion that we want to display.
    FloatRect adjustedDestRect = destRect;
    FloatSize selfSize = currentFrameSize();
    if (srcRect.size() != selfSize) {
        CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
        // When the image is scaled using high-quality interpolation, we create a temporary CGImage
        // containing only the portion we want to display. We need to do this because high-quality
        // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
        // into the destination rect. See <rdar://problem/6112909>.
        shouldUseSubimage = (interpolationQuality == kCGInterpolationHigh || interpolationQuality == kCGInterpolationDefault) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
        float xScale = srcRect.width() / destRect.width();
        float yScale = srcRect.height() / destRect.height();
        if (shouldUseSubimage) {
            FloatRect subimageRect = srcRect;
            float leftPadding = srcRect.x() - floorf(srcRect.x());
            float topPadding = srcRect.y() - floorf(srcRect.y());

            subimageRect.move(-leftPadding, -topPadding);
            adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);

            subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
            adjustedDestRect.setWidth(subimageRect.width() / xScale);

            subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
            adjustedDestRect.setHeight(subimageRect.height() / yScale);

            image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
            if (currHeight < srcRect.bottom()) {
                ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
                adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
            }
        } else {
            adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
            adjustedDestRect.setSize(FloatSize(selfSize.width() / xScale, selfSize.height() / yScale));
        }

        CGContextClipToRect(context, destRect);
    }

    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    if (!shouldUseSubimage && currHeight < selfSize.height())
        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());

    ctxt->setCompositeOperation(compositeOp);

    // Flip the coords.
    CGContextScaleCTM(context, 1, -1);
    adjustedDestRect.setY(-adjustedDestRect.bottom());

    // Adjust the color space.
    image = imageWithColorSpace(image.get(), styleColorSpace);

    // Draw the image.
    CGContextDrawImage(context, adjustedDestRect, image.get());

    ctxt->restore();

    if (imageObserver())
        imageObserver()->didDraw(this);
}