CGImageRef BitmapImage::getCGImageRef() { return frameAtIndex(0); }
PassNativeImagePtr BitmapImage::nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
bool BitmapImage::currentFrameIsLazyDecoded() { RefPtr<SkImage> image = frameAtIndex(currentFrame()); return image && image->isLazyGenerated(); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { FloatRect srcRect(src); FloatRect dstRect(dst); if (dstRect.width() == 0.0f || dstRect.height() == 0.0f || srcRect.width() == 0.0f || srcRect.height() == 0.0f) return; startAnimation(); cairo_surface_t* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(context, dstRect, solidColor(), styleColorSpace, op); return; } IntSize selfSize = size(); cairo_t* cr = context->platformContext(); context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); // If we're drawing a sub portion of the image or scaling then create // a pattern transformation on the image and draw the transformed pattern. // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD); float scaleX = srcRect.width() / dstRect.width(); float scaleY = srcRect.height() / dstRect.height(); cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, srcRect.x(), srcRect.y() }; cairo_pattern_set_matrix(pattern, &matrix); // Draw the shadow #if ENABLE(FILTERS) FloatSize shadowOffset; float shadowBlur; Color shadowColor; if (context->getShadow(shadowOffset, shadowBlur, shadowColor)) { IntSize shadowBufferSize; FloatRect shadowRect; float radius = 0; context->calculateShadowBufferDimensions(shadowBufferSize, shadowRect, radius, dstRect, shadowOffset, shadowBlur); shadowColor = colorWithOverrideAlpha(shadowColor.rgb(), (shadowColor.alpha() * context->getAlpha()) / 255.f); //draw shadow into a new ImageBuffer OwnPtr<ImageBuffer> shadowBuffer = ImageBuffer::create(shadowBufferSize); cairo_t* shadowContext = shadowBuffer->context()->platformContext(); cairo_set_source(shadowContext, pattern); cairo_translate(shadowContext, -dstRect.x(), -dstRect.y()); cairo_rectangle(shadowContext, 0, 0, dstRect.width(), dstRect.height()); cairo_fill(shadowContext); context->applyPlatformShadow(shadowBuffer.release(), shadowColor, shadowRect, radius); } #endif // Draw the image. cairo_translate(cr, dstRect.x(), dstRect.y()); cairo_set_source(cr, pattern); cairo_pattern_destroy(pattern); cairo_rectangle(cr, 0, 0, dstRect.width(), dstRect.height()); cairo_clip(cr); cairo_paint_with_alpha(cr, context->getAlpha()); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator compositeOp) { startAnimation(); 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(), compositeOp); return; } float currHeight = CGImageGetHeight(image); 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(); 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 = CGImageCreateWithImageInRect(image, subimageRect); if (currHeight < srcRect.bottom()) { ASSERT(CGImageGetHeight(image) == currHeight - CGRectIntegral(srcRect).origin.y); adjustedDestRect.setHeight(CGImageGetHeight(image) / 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()); // Draw the image. CGContextDrawImage(context, adjustedDestRect, image); if (shouldUseSubimage) CGImageRelease(image); ctxt->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
PassRefPtr<SkImage> BitmapImage::imageForCurrentFrame() { return frameAtIndex(currentFrame()); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { if (!m_source.initialized()) return; if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op); return; } #if USE(WXGC) wxGCDC* context = (wxGCDC*)ctxt->platformContext(); wxGraphicsContext* gc = context->GetGraphicsContext(); wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame); #else wxDC* context = ctxt->platformContext(); wxBitmap* bitmap = frameAtIndex(m_currentFrame); #endif startAnimation(); if (!bitmap) // If it's too early we won't have an image yet. return; // If we're drawing a sub portion of the image or scaling then create // a pattern transformation on the image and draw the transformed pattern. // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html // FIXME: NYI ctxt->save(); // Set the compositing operation. ctxt->setCompositeOperation(op); #if USE(WXGC) float scaleX = src.width() / dst.width(); float scaleY = src.height() / dst.height(); FloatRect adjustedDestRect = dst; FloatSize selfSize = currentFrameSize(); if (src.size() != selfSize) { adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY)); adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY)); } gc->Clip(dst.x(), dst.y(), dst.width(), dst.height()); #if wxCHECK_VERSION(2,9,0) gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); #else gc->DrawGraphicsBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); #endif #else // USE(WXGC) bitmap = getCachedResizedBitmap(bitmap, dst.size(), src); context->DrawBitmap(*bitmap, dst.x(), dst.y(), true); #endif ctxt->restore(); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op) { if (!m_source.initialized()) return; if (mayFillWithSolidColor()) { fillWithSolidColor(ctxt, dst, solidColor(), op); return; } #if USE(WXGC) wxGCDC* context = (wxGCDC*)ctxt->platformContext(); wxGraphicsContext* gc = context->GetGraphicsContext(); #else wxWindowDC* context = ctxt->platformContext(); #endif startAnimation(); wxBitmap* bitmap = frameAtIndex(m_currentFrame); if (!bitmap) // If it's too early we won't have an image yet. return; // If we're drawing a sub portion of the image or scaling then create // a pattern transformation on the image and draw the transformed pattern. // Test using example site at http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html // FIXME: NYI ctxt->save(); // Set the compositing operation. ctxt->setCompositeOperation(op); #if USE(WXGC) float scaleX = src.width() / dst.width(); float scaleY = src.height() / dst.height(); FloatRect adjustedDestRect = dst; FloatSize selfSize = currentFrameSize(); if (src.size() != selfSize) { adjustedDestRect.setLocation(FloatPoint(dst.x() - src.x() / scaleX, dst.y() - src.y() / scaleY)); adjustedDestRect.setSize(FloatSize(selfSize.width() / scaleX, selfSize.height() / scaleY)); } // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly. int currHeight = bitmap->GetHeight(); if (currHeight < selfSize.height()) adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height()); gc->DrawBitmap(*bitmap, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); #else IntRect srcIntRect(src); IntRect dstIntRect(dst); bool rescaling = false; if ((dstIntRect.width() != srcIntRect.width()) || (dstIntRect.height() != srcIntRect.height())) { rescaling = true; wxImage img = bitmap->ConvertToImage(); img.Rescale(dstIntRect.width(), dstIntRect.height()); bitmap = new wxBitmap(img); } wxMemoryDC mydc; ASSERT(bitmap->GetRefData()); mydc.SelectObject(*bitmap); context->Blit((wxCoord)dstIntRect.x(),(wxCoord)dstIntRect.y(), (wxCoord)dstIntRect.width(), (wxCoord)dstIntRect.height(), &mydc, (wxCoord)srcIntRect.x(), (wxCoord)srcIntRect.y(), wxCOPY, true); mydc.SelectObject(wxNullBitmap); // NB: delete is causing crashes during page load, but not during the deletion // itself. It occurs later on when a valid bitmap created in frameAtIndex // suddenly becomes invalid after returning. It's possible these errors deal // with reentrancy and threding problems. //delete bitmap; if (rescaling) { delete bitmap; bitmap = NULL; } #endif ctxt->restore(); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, CompositeOperator op) { SDL_Surface* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; FloatRect sourceRect(src); FloatRect destRect(dst); if (mayFillWithSolidColor()) { fillWithSolidColor(context, destRect, solidColor(), op); return; } // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); SDL_Surface* cr = context->platformContext(); float scaleX = destRect.width() / sourceRect.width(); float scaleY = destRect.height() / sourceRect.height(); // Draw the image. SDL_Rect srcRect, dstRect; srcRect.x = static_cast<Sint16>(src.x()); srcRect.y = static_cast<Sint16>(src.y()); if (0 == sourceRect.width()) srcRect.w = image->w; else srcRect.w = static_cast<Uint16>(sourceRect.width()); if (0 == sourceRect.height()) srcRect.h = image->h; else srcRect.h = static_cast<Uint16>(sourceRect.height()); dstRect.x = static_cast<Sint16>(destRect.x() + context->origin().x()); dstRect.y = static_cast<Sint16>(destRect.y() + context->origin().y()); dstRect.w = static_cast<Sint16>(destRect.width()); dstRect.h = static_cast<Sint16>(destRect.height()); if ((scaleX != 1.0)||(scaleY != 1.0)) { srcRect.x = static_cast<Sint16>(src.x() * scaleX); srcRect.y = static_cast<Sint16>(src.y() * scaleY); srcRect.w = dstRect.w; srcRect.h = dstRect.h; } if (sourceRect != destRect) { if (context->transparencyLayer() == 1.0) { if ((scaleX != 1.0) || (scaleY != 1.0)) { SDL_Surface *surface = zoomSurface(image, scaleX, scaleY, SMOOTHING_OFF); SDL_BlitSurface(surface, &srcRect, cr, &dstRect); SDL_FreeSurface(surface); } else SDL_BlitSurface(image, &srcRect, cr, &dstRect); } else { SDL_Surface *surfaceWithAlpha = applyTransparency(image, static_cast<int> (context->transparencyLayer() * 255)); if ((scaleX != 1.0) || (scaleY != 1.0)) { SDL_Surface *surface = zoomSurface(surfaceWithAlpha, scaleX, scaleY, SMOOTHING_OFF); SDL_BlitSurface(surface, &srcRect, cr, &dstRect); SDL_FreeSurface(surface); } else SDL_BlitSurface(surfaceWithAlpha, &srcRect, cr, &dstRect); SDL_FreeSurface(surfaceWithAlpha); } } else if (context->transparencyLayer() == 1.0) SDL_BlitSurface(image, &srcRect, cr, &dstRect); else { SDL_Surface *surfaceWithAlpha = applyTransparency(image, static_cast<int> (context->transparencyLayer() * 255)); SDL_BlitSurface(surfaceWithAlpha, &srcRect, cr, &dstRect); SDL_FreeSurface(surfaceWithAlpha); } startAnimation(); if (imageObserver()) imageObserver()->didDraw(this); }
PassRefPtr<NativeImageSkia> BitmapImage::nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); }
GdkPixbuf* BitmapImage::getGdkPixbuf() { return cairoImageSurfaceToGdkPixbuf(frameAtIndex(currentFrame())); }
void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, CompositeOperator op) { if (!m_source.initialized()) return; cairo_surface_t* image = frameAtIndex(m_currentFrame); if (!image) // If it's too early we won't have an image yet. return; IntSize intrinsicImageSize = size(); FloatRect srcRect(srcPoint, intrinsicImageSize); FloatPoint point = srcPoint; // Check and see if a single draw of the image can cover the entire area we are supposed to tile. float tileWidth = size().width(); float tileHeight = size().height(); // If the scale is not equal to the intrinsic size of the image, set transform matrix // to the appropriate scalar matrix, scale the source point, and set the size of the // scaled tile. float scaleX = 1.0; float scaleY = 1.0; cairo_matrix_t mat; cairo_matrix_init_identity(&mat); if (tileSize.width() != intrinsicImageSize.width() || tileSize.height() != intrinsicImageSize.height()) { scaleX = intrinsicImageSize.width() / tileSize.width(); scaleY = intrinsicImageSize.height() / tileSize.height(); cairo_matrix_init_scale(&mat, scaleX, scaleY); tileWidth = tileSize.width(); tileHeight = tileSize.height(); } // We could get interesting source offsets (negative ones or positive ones. Deal with both // out of bounds cases. float dstTileX = dstRect.x() + fmodf(fmodf(-point.x(), tileWidth) - tileWidth, tileWidth); float dstTileY = dstRect.y() + fmodf(fmodf(-point.y(), tileHeight) - tileHeight, tileHeight); FloatRect dstTileRect(dstTileX, dstTileY, tileWidth, tileHeight); float srcX = dstRect.x() - dstTileRect.x(); float srcY = dstRect.y() - dstTileRect.y(); // If the single image draw covers the whole area, then just draw once. if (dstTileRect.contains(dstRect)) { draw(ctxt, dstRect, FloatRect(srcX * scaleX, srcY * scaleY, dstRect.width() * scaleX, dstRect.height() * scaleY), op); return; } // We have to tile. cairo_t* context = ctxt->platformContext(); cairo_save(context); // Set the compositing operation. setCompositingOperation(context, op, frameHasAlphaAtIndex(m_currentFrame)); cairo_translate(context, dstTileRect.x(), dstTileRect.y()); cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_matrix(pattern, &mat); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); // Draw the image. cairo_set_source(context, pattern); cairo_rectangle(context, srcX, srcY, dstRect.width(), dstRect.height()); cairo_fill(context); cairo_restore(context); startAnimation(); }
bool BitmapImage::bitmapForCurrentFrame(SkBitmap* bitmap) { return frameAtIndex(currentFrame(), bitmap); }