Home | History | Annotate | Download | only in frame
      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/frame/ImageBitmap.h"
      7 
      8 #include "core/html/HTMLCanvasElement.h"
      9 #include "core/html/HTMLVideoElement.h"
     10 #include "core/html/ImageData.h"
     11 #include "core/html/canvas/CanvasRenderingContext.h"
     12 #include "platform/graphics/BitmapImage.h"
     13 #include "platform/graphics/GraphicsContext.h"
     14 #include "platform/graphics/ImageBuffer.h"
     15 #include "wtf/RefPtr.h"
     16 
     17 using namespace std;
     18 
     19 namespace WebCore {
     20 
     21 static inline IntRect normalizeRect(const IntRect& rect)
     22 {
     23     return IntRect(min(rect.x(), rect.maxX()),
     24         min(rect.y(), rect.maxY()),
     25         max(rect.width(), -rect.width()),
     26         max(rect.height(), -rect.height()));
     27 }
     28 
     29 static inline PassRefPtr<Image> cropImage(Image* image, const IntRect& cropRect)
     30 {
     31     IntRect intersectRect = intersection(IntRect(IntPoint(), image->size()), cropRect);
     32     if (!intersectRect.width() || !intersectRect.height())
     33         return 0;
     34 
     35     SkBitmap cropped;
     36     image->nativeImageForCurrentFrame()->bitmap().extractSubset(&cropped, intersectRect);
     37     return BitmapImage::create(NativeImageSkia::create(cropped));
     38 }
     39 
     40 ImageBitmap::ImageBitmap(HTMLImageElement* image, const IntRect& cropRect)
     41     : m_imageElement(image)
     42     , m_bitmap(0)
     43     , m_cropRect(cropRect)
     44 {
     45     IntRect srcRect = intersection(cropRect, IntRect(0, 0, image->width(), image->height()));
     46     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     47     m_bitmapOffset = srcRect.location();
     48 
     49     if (!srcRect.width() || !srcRect.height())
     50         m_imageElement = 0;
     51     else
     52         m_imageElement->addClient(this);
     53 
     54     ScriptWrappable::init(this);
     55 }
     56 
     57 ImageBitmap::ImageBitmap(HTMLVideoElement* video, const IntRect& cropRect)
     58     : m_imageElement(0)
     59     , m_cropRect(cropRect)
     60     , m_bitmapOffset(IntPoint())
     61 {
     62     IntRect videoRect = IntRect(IntPoint(), video->player()->naturalSize());
     63     IntRect srcRect = intersection(cropRect, videoRect);
     64     IntRect dstRect(IntPoint(), srcRect.size());
     65 
     66     OwnPtr<ImageBuffer> buf = ImageBuffer::create(videoRect.size());
     67     if (!buf)
     68         return;
     69     GraphicsContext* c = buf->context();
     70     c->clip(dstRect);
     71     c->translate(-srcRect.x(), -srcRect.y());
     72     video->paintCurrentFrameInContext(c, videoRect);
     73     m_bitmap = buf->copyImage(DontCopyBackingStore);
     74     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     75 
     76     ScriptWrappable::init(this);
     77 }
     78 
     79 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, const IntRect& cropRect)
     80     : m_imageElement(0)
     81     , m_cropRect(cropRect)
     82     , m_bitmapOffset(IntPoint())
     83 {
     84     CanvasRenderingContext* sourceContext = canvas->renderingContext();
     85     if (sourceContext && sourceContext->is3d())
     86         sourceContext->paintRenderingResultsToCanvas();
     87 
     88     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), canvas->size()));
     89     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())), srcRect.size());
     90     m_bitmap = cropImage(canvas->buffer()->copyImage(CopyBackingStore).get(), cropRect);
     91 
     92     ScriptWrappable::init(this);
     93 }
     94 
     95 ImageBitmap::ImageBitmap(ImageData* data, const IntRect& cropRect)
     96     : m_imageElement(0)
     97     , m_cropRect(cropRect)
     98     , m_bitmapOffset(IntPoint())
     99 {
    100     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), data->size()));
    101 
    102     OwnPtr<ImageBuffer> buf = ImageBuffer::create(data->size());
    103     if (!buf)
    104         return;
    105     if (srcRect.width() > 0 && srcRect.height() > 0)
    106         buf->putByteArray(Premultiplied, data->data(), data->size(), srcRect, IntPoint(min(0, -cropRect.x()), min(0, -cropRect.y())));
    107 
    108     m_bitmap = buf->copyImage(DontCopyBackingStore);
    109     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())),  srcRect.size());
    110 
    111     ScriptWrappable::init(this);
    112 }
    113 
    114 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, const IntRect& cropRect)
    115     : m_imageElement(bitmap->imageElement())
    116     , m_bitmap(0)
    117     , m_cropRect(cropRect)
    118     , m_bitmapOffset(IntPoint())
    119 {
    120     IntRect oldBitmapRect = bitmap->bitmapRect();
    121     IntRect srcRect = intersection(cropRect, oldBitmapRect);
    122     m_bitmapRect = IntRect(IntPoint(max(0, oldBitmapRect.x() - cropRect.x()), max(0, oldBitmapRect.y() - cropRect.y())), srcRect.size());
    123 
    124     if (m_imageElement) {
    125         m_imageElement->addClient(this);
    126         m_bitmapOffset = srcRect.location();
    127     } else if (bitmap->bitmapImage()) {
    128         IntRect adjustedCropRect(IntPoint(cropRect.x() -oldBitmapRect.x(), cropRect.y() - oldBitmapRect.y()), cropRect.size());
    129         m_bitmap = cropImage(bitmap->bitmapImage().get(), adjustedCropRect);
    130     }
    131 
    132     ScriptWrappable::init(this);
    133 }
    134 
    135 ImageBitmap::ImageBitmap(Image* image, const IntRect& cropRect)
    136     : m_imageElement(0)
    137     , m_cropRect(cropRect)
    138 {
    139     IntRect srcRect = intersection(cropRect, IntRect(IntPoint(), image->size()));
    140     m_bitmap = cropImage(image, cropRect);
    141     m_bitmapRect = IntRect(IntPoint(max(0, -cropRect.x()), max(0, -cropRect.y())),  srcRect.size());
    142 
    143     ScriptWrappable::init(this);
    144 }
    145 
    146 ImageBitmap::~ImageBitmap()
    147 {
    148     if (m_imageElement)
    149         m_imageElement->removeClient(this);
    150 }
    151 
    152 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect)
    153 {
    154     IntRect normalizedCropRect = normalizeRect(cropRect);
    155     return adoptRef(new ImageBitmap(image, normalizedCropRect));
    156 }
    157 
    158 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect)
    159 {
    160     IntRect normalizedCropRect = normalizeRect(cropRect);
    161     return adoptRef(new ImageBitmap(video, normalizedCropRect));
    162 }
    163 
    164 PassRefPtr<ImageBitmap> ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect)
    165 {
    166     IntRect normalizedCropRect = normalizeRect(cropRect);
    167     return adoptRef(new ImageBitmap(canvas, normalizedCropRect));
    168 }
    169 
    170 PassRefPtr<ImageBitmap> ImageBitmap::create(ImageData* data, const IntRect& cropRect)
    171 {
    172     IntRect normalizedCropRect = normalizeRect(cropRect);
    173     return adoptRef(new ImageBitmap(data, normalizedCropRect));
    174 }
    175 
    176 PassRefPtr<ImageBitmap> ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect)
    177 {
    178     IntRect normalizedCropRect = normalizeRect(cropRect);
    179     return adoptRef(new ImageBitmap(bitmap, normalizedCropRect));
    180 }
    181 
    182 PassRefPtr<ImageBitmap> ImageBitmap::create(Image* image, const IntRect& cropRect)
    183 {
    184     IntRect normalizedCropRect = normalizeRect(cropRect);
    185     return adoptRef(new ImageBitmap(image, normalizedCropRect));
    186 }
    187 
    188 void ImageBitmap::notifyImageSourceChanged()
    189 {
    190     m_bitmap = cropImage(m_imageElement->cachedImage()->image(), m_cropRect);
    191     m_bitmapOffset = IntPoint();
    192     m_imageElement = 0;
    193 }
    194 
    195 PassRefPtr<Image> ImageBitmap::bitmapImage() const
    196 {
    197     ASSERT((m_imageElement || m_bitmap || !m_bitmapRect.width() || !m_bitmapRect.height()) && (!m_imageElement || !m_bitmap));
    198     if (m_imageElement)
    199         return m_imageElement->cachedImage()->image();
    200     return m_bitmap;
    201 }
    202 
    203 }
    204