void drawNativeImage(const NativeImagePtr& image, GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect, const IntSize&, CompositeOperator op, BlendMode mode, const ImageOrientation& orientation) { context.save(); // Set the compositing operation. if (op == CompositeSourceOver && mode == BlendModeNormal && !nativeImageHasAlpha(image)) context.setCompositeOperation(CompositeCopy); else context.setCompositeOperation(op, mode); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) IntSize scaledSize = nativeImageSize(image); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); #else FloatRect adjustedSrcRect(srcRect); #endif FloatRect adjustedDestRect = destRect; if (orientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context.translate(destRect.x(), destRect.y()); adjustedDestRect.setLocation(FloatPoint()); context.concatCTM(orientation.transformFromDefault(adjustedDestRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. adjustedDestRect.setSize(adjustedDestRect.size().transposedSize()); } } context.platformContext()->drawSurfaceToContext(image.get(), adjustedDestRect, adjustedSrcRect, context); context.restore(); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum shouldRespectImageOrientation) { TRACE_EVENT0("skia", "BitmapImage::draw"); SkBitmap bitmap; if (!bitmapForCurrentFrame(&bitmap)) return; // It's too early and we don't have an image yet. FloatRect normDstRect = adjustForNegativeSize(dstRect); FloatRect normSrcRect = adjustForNegativeSize(srcRect); normSrcRect.intersect(FloatRect(0, 0, bitmap.width(), bitmap.height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); GraphicsContextStateSaver saveContext(*ctxt, false); if (orientation != DefaultImageOrientation) { saveContext.save(); // ImageOrientation expects the origin to be at (0, 0) ctxt->translate(normDstRect.x(), normDstRect.y()); normDstRect.setLocation(FloatPoint()); ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rect will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRect.height(), normDstRect.width()); } } bool isLazyDecoded = DeferredImageDecoder::isLazyDecoded(bitmap); bool isOpaque = bitmap.isOpaque(); { SkPaint paint; SkRect skSrcRect = normSrcRect; int initialSaveCount = ctxt->preparePaintForDrawRectToRect(&paint, skSrcRect, normDstRect, compositeOp, !isOpaque, isLazyDecoded, bitmap.isImmutable()); // We want to filter it if we decided to do interpolation above, or if // there is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so we // don't send extra pixels. ctxt->drawBitmapRect(bitmap, &skSrcRect, normDstRect, &paint); ctxt->canvas()->restoreToCount(initialSaveCount); } if (isLazyDecoded) PlatformInstrumentation::didDrawLazyPixelRef(bitmap.getGenerationID()); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); startAnimation(); }
void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op, BlendMode, RespectImageOrientationEnum shouldRespectImageOrientation) { if (!dst.width() || !dst.height() || !src.width() || !src.height()) return; startAnimation(); NativeImageCairo* nativeImage = frameAtIndex(m_currentFrame); if (!nativeImage) // If it's too early we won't have an image yet. return; if (mayFillWithSolidColor()) { fillWithSolidColor(context, dst, solidColor(), styleColorSpace, op); return; } context->save(); // Set the compositing operation. if (op == CompositeSourceOver && !frameHasAlphaAtIndex(m_currentFrame)) context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) cairo_surface_t* surface = nativeImage->surface(); IntSize scaledSize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(src, scaledSize); #else FloatRect adjustedSrcRect(src); #endif ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); FloatRect dstRect = dst; if (orientation != DefaultImageOrientation) { // ImageOrientation expects the origin to be at (0, 0). context->translate(dstRect.x(), dstRect.y()); dstRect.setLocation(FloatPoint()); context->concatCTM(orientation.transformFromDefault(dstRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rectangle will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. dstRect = FloatRect(dstRect.x(), dstRect.y(), dstRect.height(), dstRect.width()); } } context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, adjustedSrcRect, context); context->restore(); if (imageObserver()) imageObserver()->didDraw(this); }
void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, RespectImageOrientationEnum shouldRespectImageOrientation) { if (!m_source.initialized()) return; // Spin the animation to the correct frame before we try to draw it, so we // don't draw an old frame and then immediately need to draw a newer one, // causing flicker and wasting CPU. startAnimation(); NativeImageSkia* bm = nativeImageForCurrentFrame(); if (!bm) return; // It's too early and we don't have an image yet. FloatRect normDstRect = normalizeRect(dstRect); FloatRect normSrcRect = normalizeRect(srcRect); normSrcRect.intersect(FloatRect(0, 0, bm->bitmap().width(), bm->bitmap().height())); if (normSrcRect.isEmpty() || normDstRect.isEmpty()) return; // Nothing to draw. ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); GraphicsContextStateSaver saveContext(*ctxt, false); if (orientation != DefaultImageOrientation) { saveContext.save(); // ImageOrientation expects the origin to be at (0, 0) ctxt->translate(normDstRect.x(), normDstRect.y()); normDstRect.setLocation(FloatPoint()); ctxt->concatCTM(orientation.transformFromDefault(normDstRect.size())); if (orientation.usesWidthAsHeight()) { // The destination rect will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. normDstRect = FloatRect(normDstRect.x(), normDstRect.y(), normDstRect.height(), normDstRect.width()); } } paintSkBitmap(ctxt->platformContext(), *bm, normSrcRect, normDstRect, WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); }
void BitmapImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dstRect, const FloatRect& srcRect, RespectImageOrientationEnum shouldRespectImageOrientation, ImageClampingMode clampMode) { TRACE_EVENT0("skia", "BitmapImage::draw"); RefPtr<SkImage> image = imageForCurrentFrame(); if (!image) return; // It's too early and we don't have an image yet. FloatRect adjustedSrcRect = srcRect; adjustedSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); if (adjustedSrcRect.isEmpty() || dstRect.isEmpty()) return; // Nothing to draw. ImageOrientation orientation = DefaultImageOrientation; if (shouldRespectImageOrientation == RespectImageOrientation) orientation = frameOrientationAtIndex(m_currentFrame); int initialSaveCount = canvas->getSaveCount(); FloatRect adjustedDstRect = dstRect; if (orientation != DefaultImageOrientation) { canvas->save(); // ImageOrientation expects the origin to be at (0, 0) canvas->translate(adjustedDstRect.x(), adjustedDstRect.y()); adjustedDstRect.setLocation(FloatPoint()); canvas->concat(affineTransformToSkMatrix(orientation.transformFromDefault(adjustedDstRect.size()))); if (orientation.usesWidthAsHeight()) { // The destination rect will have it's width and height already reversed for the orientation of // the image, as it was needed for page layout, so we need to reverse it back here. adjustedDstRect = FloatRect(adjustedDstRect.x(), adjustedDstRect.y(), adjustedDstRect.height(), adjustedDstRect.width()); } } SkRect skSrcRect = adjustedSrcRect; canvas->drawImageRect(image.get(), skSrcRect, adjustedDstRect, &paint, WebCoreClampingModeToSkiaRectConstraint(clampMode)); canvas->restoreToCount(initialSaveCount); if (currentFrameIsLazyDecoded()) PlatformInstrumentation::didDrawLazyPixelRef(image->uniqueID()); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); startAnimation(); }
PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBitmap& bitmap, ImageOrientation orientation) { RefPtr<BitmapImage> result = create(bitmap); result->m_frames[0].m_orientation = orientation; if (orientation.usesWidthAsHeight()) result->m_sizeRespectingOrientation = IntSize(result->m_size.height(), result->m_size.width()); return result.release(); }
PassOwnPtr<DragImage> DragImage::create(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation, float deviceScaleFactor) { if (!image) return nullptr; RefPtr<NativeImageSkia> bitmap = image->nativeImageForCurrentFrame(); if (!bitmap) return nullptr; if (image->isBitmapImage()) { ImageOrientation orientation = DefaultImageOrientation; BitmapImage* bitmapImage = toBitmapImage(image); IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation(); if (shouldRespectImageOrientation == RespectImageOrientation) orientation = bitmapImage->currentFrameOrientation(); if (orientation != DefaultImageOrientation) { FloatRect destRect(FloatPoint(), sizeRespectingOrientation); if (orientation.usesWidthAsHeight()) destRect = destRect.transposedRect(); SkBitmap skBitmap; skBitmap.setConfig( SkBitmap::kARGB_8888_Config, sizeRespectingOrientation.width(), sizeRespectingOrientation.height()); if (!skBitmap.allocPixels()) return nullptr; SkCanvas canvas(skBitmap); canvas.concat(affineTransformToSkMatrix(orientation.transformFromDefault(sizeRespectingOrientation))); canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect); return adoptPtr(new DragImage(skBitmap, deviceScaleFactor)); } } SkBitmap skBitmap; #if defined(SBROWSER_GPU_RASTERIZATION_ENABLE) if (!bitmap->bitmap().copyTo(&skBitmap, kPMColor_SkColorType)) #else if (!bitmap->bitmap().copyTo(&skBitmap, SkBitmap::kARGB_8888_Config)) #endif return nullptr; return adoptPtr(new DragImage(skBitmap, deviceScaleFactor)); }
DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation) { if (!image) return 0; NativeImageSkia* bitmap = image->nativeImageForCurrentFrame(); if (!bitmap) return 0; DragImageChromium* dragImageChromium = new DragImageChromium; dragImageChromium->bitmap = new SkBitmap(); dragImageChromium->resolutionScale = bitmap->resolutionScale(); if (image->isBitmapImage()) { ImageOrientation orientation = DefaultImageOrientation; BitmapImage* bitmapImage = static_cast<BitmapImage*>(image); IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation(); if (shouldRespectImageOrientation == RespectImageOrientation) orientation = bitmapImage->currentFrameOrientation(); if (orientation != DefaultImageOrientation) { // Construct a correctly-rotated copy of the image to use as the drag image. dragImageChromium->bitmap->setConfig( SkBitmap::kARGB_8888_Config, sizeRespectingOrientation.width(), sizeRespectingOrientation.height()); dragImageChromium->bitmap->allocPixels(); FloatRect destRect(FloatPoint(), sizeRespectingOrientation); SkCanvas canvas(*dragImageChromium->bitmap); canvas.concat(orientation.transformFromDefault(sizeRespectingOrientation)); if (orientation.usesWidthAsHeight()) destRect = FloatRect(destRect.x(), destRect.y(), destRect.height(), destRect.width()); canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect); return dragImageChromium; } } bitmap->bitmap().copyTo(dragImageChromium->bitmap, SkBitmap::kARGB_8888_Config); return dragImageChromium; }
PassRefPtr<BitmapImage> BitmapImage::createWithOrientationForTesting(const SkBitmap& bitmap, ImageOrientation orientation) { if (bitmap.isNull()) { return BitmapImage::create(); } RefPtr<BitmapImage> result = adoptRef(new BitmapImage(bitmap)); result->m_frames[0].m_orientation = orientation; if (orientation.usesWidthAsHeight()) result->m_sizeRespectingOrientation = result->m_size.transposedSize(); return result.release(); }
PassRefPtr<SkImage> DragImage::resizeAndOrientImage(PassRefPtr<SkImage> image, ImageOrientation orientation, FloatSize imageScale, float opacity, InterpolationQuality interpolationQuality) { IntSize size(image->width(), image->height()); size.scale(imageScale.width(), imageScale.height()); AffineTransform transform; if (orientation != DefaultImageOrientation) { if (orientation.usesWidthAsHeight()) size = size.transposedSize(); transform *= orientation.transformFromDefault(size); } transform.scaleNonUniform(imageScale.width(), imageScale.height()); if (size.isEmpty()) return nullptr; if (transform.isIdentity() && opacity == 1) { // Nothing to adjust, just use the original. ASSERT(image->width() == size.width()); ASSERT(image->height() == size.height()); return image; } RefPtr<SkSurface> surface = adoptRef(SkSurface::NewRasterN32Premul(size.width(), size.height())); if (!surface) return nullptr; SkPaint paint; ASSERT(opacity >= 0 && opacity <= 1); paint.setAlpha(opacity * 255); paint.setFilterQuality(interpolationQuality == InterpolationNone ? kNone_SkFilterQuality : kHigh_SkFilterQuality); SkCanvas* canvas = surface->getCanvas(); canvas->clear(SK_ColorTRANSPARENT); canvas->concat(affineTransformToSkMatrix(transform)); canvas->drawImage(image.get(), 0, 0, &paint); return adoptRef(surface->newImageSnapshot()); }
PassOwnPtr<DragImage> DragImage::create(Image* image, RespectImageOrientationEnum shouldRespectImageOrientation, float deviceScaleFactor) { if (!image) return nullptr; RefPtr<NativeImageSkia> bitmap = image->nativeImageForCurrentFrame(); if (!bitmap) return nullptr; if (image->isBitmapImage()) { ImageOrientation orientation = DefaultImageOrientation; BitmapImage* bitmapImage = toBitmapImage(image); IntSize sizeRespectingOrientation = bitmapImage->sizeRespectingOrientation(); if (shouldRespectImageOrientation == RespectImageOrientation) orientation = bitmapImage->currentFrameOrientation(); if (orientation != DefaultImageOrientation) { FloatRect destRect(FloatPoint(), sizeRespectingOrientation); if (orientation.usesWidthAsHeight()) destRect = destRect.transposedRect(); SkBitmap skBitmap; if (!skBitmap.tryAllocN32Pixels(sizeRespectingOrientation.width(), sizeRespectingOrientation.height())) return nullptr; SkCanvas canvas(skBitmap); canvas.concat(affineTransformToSkMatrix(orientation.transformFromDefault(sizeRespectingOrientation))); canvas.drawBitmapRect(bitmap->bitmap(), 0, destRect); return adoptPtr(new DragImage(skBitmap, deviceScaleFactor)); } } SkBitmap skBitmap; if (!bitmap->bitmap().copyTo(&skBitmap, kN32_SkColorType)) return nullptr; return adoptPtr(new DragImage(skBitmap, deviceScaleFactor)); }