Home | History | Annotate | Download | only in page
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 #include "core/page/ImageBitmap.h"
      7 
      8 #include "core/html/HTMLCanvasElement.h"
      9 #include "core/html/HTMLImageElement.h"
     10 #include "core/html/HTMLVideoElement.h"
     11 #include "core/html/ImageData.h"
     12 #include "core/platform/graphics/BitmapImage.h"
     13 #include "core/platform/graphics/GraphicsContext.h"
     14 #include "wtf/RefPtr.h"
     15 
     16 using namespace std;
     17 
     18 namespace WebCore {
     19 
     20 static inline IntRect normalizeRect(const IntRect& rect)
     21 {
     22     return IntRect(min(rect.x(), rect.maxX()),
     23         min(rect.y(), rect.maxY()),
     24         max(rect.width(), -rect.width()),
     25         max(rect.height(), -rect.height()));
     26 }
     27 
     28 static inline PassRefPtr<Image> cropImage(Image* image, const IntRect& cropRect)
     29 {
     30     SkBitmap cropped;
     31     image->nativeImageForCurrentFrame()->bitmap().extractSubset(&cropped, cropRect);
     32     return BitmapImage::create(NativeImageSkia::create(cropped));
     33 }
     34 
     35 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect)
     36     : m_cropRect(cropRect)
     37     , m_bitmap(0)
     38     , m_imageElement(image)
     39 {
     40     IntRect srcRect = intersection(cropRect, IntRect(0, 0, image->width(), image->height()));
     41     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     42     m_bitmapOffset = srcRect.location();
     43 
     44     if (!srcRect.width() || !srcRect.height())
     45         m_imageElement = 0;
     46     else
     47         m_imageElement->addClient(this);
     48 
     49     ScriptWrappable::init(this);
     50 }
     51 
     52 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect)
     53     : m_cropRect(cropRect)
     54     , m_imageElement(0)
     55     , m_bitmapOffset(IntPoint())
     56 {
     57     IntRect videoRect = IntRect(IntPoint(), video->player()->naturalSize());
     58     IntRect srcRect = intersection(cropRect, videoRect);
     59     IntRect dstRect(IntPoint(), srcRect.size());
     60 
     61     m_buffer = ImageBuffer::create(videoRect.size());
     62     GraphicsContext* c = m_buffer->context();
     63     c->clip(dstRect);
     64     c->translate(-srcRect.x(), -srcRect.y());
     65     video->paintCurrentFrameInContext(c, videoRect);
     66     m_bitmap = m_buffer->copyImage(DontCopyBackingStore);
     67     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     68 
     69     ScriptWrappable::init(this);
     70 }
     71 
     72 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect)
     73     : m_cropRect(cropRect)
     74     , m_imageElement(0)
     75     , m_bitmapOffset(IntPoint())
     76 {
     77     IntSize canvasSize = canvas->size();
     78     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), canvasSize));
     79     IntRect dstRect(IntPoint(), srcRect.size());
     80 
     81     m_buffer = ImageBuffer::create(canvasSize);
     82     m_buffer->context()->drawImageBuffer(canvas->buffer(), dstRect, srcRect);
     83     m_bitmap = m_buffer->copyImage(DontCopyBackingStore);
     84     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     85 
     86     ScriptWrappable::init(this);
     87 }
     88 
     89 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect)
     90     : m_cropRect(cropRect)
     91     , m_imageElement(0)
     92     , m_bitmapOffset(IntPoint())
     93 {
     94     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size()));
     95 
     96     m_buffer = ImageBuffer::create(data->size());
     97     if (srcRect.width() > 0 && srcRect.height() > 0)
     98         m_buffer->putByteArray(Unmultiplied, data->data(), data->size(), srcRect, IntPoint(min(0, -cropRect.x()), min(0, -cropRect.y())));
     99 
    100     m_bitmap = m_buffer->copyImage(DontCopyBackingStore);
    101     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())),  srcRect.size());
    102 
    103     ScriptWrappable::init(this);
    104 }
    105 
    106 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect)
    107     : m_cropRect(cropRect)
    108     , m_bitmap(0)
    109     , m_imageElement(bitmap->imageElement())
    110     , m_bitmapOffset(IntPoint())
    111 {
    112     IntRect oldBitmapRect = bitmap->bitmapRect();
    113     IntRect srcRect = intersection(cropRect, oldBitmapRect);
    114     m_bitmapRect = IntRect(IntPoint(max(0, oldBitmapRect.x() - cropRect.x()), max(0, oldBitmapRect.y() - cropRect.y())), srcRect.size());
    115 
    116     if (m_imageElement) {
    117         m_imageElement->addClient(this);
    118         m_bitmapOffset = srcRect.location();
    119     } else if (bitmap->bitmapImage()) {
    120         IntRect adjustedCropRect(IntPoint(cropRect.x() -oldBitmapRect.x(), cropRect.y() - oldBitmapRect.y()), cropRect.size());
    121         m_bitmap = cropImage(bitmap->bitmapImage().get(), adjustedCropRect);
    122     }
    123 
    124     ScriptWrappable::init(this);
    125 }
    126 
    127 ImageBitmap::~ImageBitmap()
    128 {
    129     if (m_imageElement)
    130         m_imageElement->removeClient(this);
    131 }
    132 
    133 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect)
    134 {
    135     IntRect normalizedCropRect = normalizeRect(cropRect);
    136     RefPtr<ImageBitmap> imageBitmap(adoptRef(new ImageBitmap(image, normalizedCropRect)));
    137     return imageBitmap.release();
    138 }
    139 
    140 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect)
    141 {
    142     IntRect normalizedCropRect = normalizeRect(cropRect);
    143     RefPtr<ImageBitmap> imageBitmap(adoptRef(new ImageBitmap(video, normalizedCropRect)));
    144     return imageBitmap.release();
    145 }
    146 
    147 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect)
    148 {
    149     IntRect normalizedCropRect = normalizeRect(cropRect);
    150     RefPtr<ImageBitmap> imageBitmap(adoptRef(new ImageBitmap(canvas, normalizedCropRect)));
    151     return imageBitmap.release();
    152 }
    153 
    154 PassRefPtr<ImageBitmap> ImageBitmap::create(ImageData* data, const IntRect& cropRect)
    155 {
    156     IntRect normalizedCropRect = normalizeRect(cropRect);
    157     RefPtr<ImageBitmap> imageBitmap(adoptRef(new ImageBitmap(data, normalizedCropRect)));
    158     return imageBitmap.release();
    159 }
    160 
    161 PassRefPtr<ImageBitmap> ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect)
    162 {
    163     IntRect normalizedCropRect = normalizeRect(cropRect);
    164     RefPtr<ImageBitmap> imageBitmap(adoptRef(new ImageBitmap(bitmap, normalizedCropRect)));
    165     return imageBitmap.release();
    166 }
    167 
    168 void ImageBitmap::notifyImageSourceChanged()
    169 {
    170     m_bitmap = cropImage(m_imageElement->cachedImage()->image(), m_cropRect);
    171     m_bitmapOffset = IntPoint();
    172     m_imageElement = 0;
    173 }
    174 
    175 PassRefPtr<Image> ImageBitmap::bitmapImage() const
    176 {
    177     ASSERT((m_imageElement || m_bitmap || !m_bitmapRect.width() || !m_bitmapRect.height()) && (!m_imageElement || !m_bitmap));
    178     if (m_imageElement)
    179         return m_imageElement->cachedImage()->image();
    180     return m_bitmap;
    181 }
    182 
    183 }
    184