Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / ImageBitmap.cpp
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 nullptr;
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(nullptr)
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 = nullptr;
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(nullptr)
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(nullptr)
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(nullptr)
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(nullptr)
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(nullptr)
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 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLImageElement* image, const IntRect& cropRect)
153 {
154     IntRect normalizedCropRect = normalizeRect(cropRect);
155     return adoptRefWillBeNoop(new ImageBitmap(image, normalizedCropRect));
156 }
157
158 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLVideoElement* video, const IntRect& cropRect)
159 {
160     IntRect normalizedCropRect = normalizeRect(cropRect);
161     return adoptRefWillBeNoop(new ImageBitmap(video, normalizedCropRect));
162 }
163
164 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(HTMLCanvasElement* canvas, const IntRect& cropRect)
165 {
166     IntRect normalizedCropRect = normalizeRect(cropRect);
167     return adoptRefWillBeNoop(new ImageBitmap(canvas, normalizedCropRect));
168 }
169
170 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(ImageData* data, const IntRect& cropRect)
171 {
172     IntRect normalizedCropRect = normalizeRect(cropRect);
173     return adoptRefWillBeNoop(new ImageBitmap(data, normalizedCropRect));
174 }
175
176 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(ImageBitmap* bitmap, const IntRect& cropRect)
177 {
178     IntRect normalizedCropRect = normalizeRect(cropRect);
179     return adoptRefWillBeNoop(new ImageBitmap(bitmap, normalizedCropRect));
180 }
181
182 PassRefPtrWillBeRawPtr<ImageBitmap> ImageBitmap::create(Image* image, const IntRect& cropRect)
183 {
184     IntRect normalizedCropRect = normalizeRect(cropRect);
185     return adoptRefWillBeNoop(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 = nullptr;
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 PassRefPtr<Image> ImageBitmap::getSourceImageForCanvas(SourceImageMode, SourceImageStatus* status) const
204 {
205     *status = NormalSourceImageStatus;
206     return bitmapImage();
207 }
208
209 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, FloatRect* dstRect) const
210 {
211     FloatRect intersectRect = intersection(m_bitmapRect, *srcRect);
212     FloatRect newSrcRect = intersectRect;
213     newSrcRect.move(m_bitmapOffset - m_bitmapRect.location());
214     FloatRect newDstRect(FloatPoint(intersectRect.location() - srcRect->location()), m_bitmapRect.size());
215     newDstRect.scale(dstRect->width() / srcRect->width() * intersectRect.width() / m_bitmapRect.width(),
216         dstRect->height() / srcRect->height() * intersectRect.height() / m_bitmapRect.height());
217     newDstRect.moveBy(dstRect->location());
218     *srcRect = newSrcRect;
219     *dstRect = newDstRect;
220 }
221
222 FloatSize ImageBitmap::sourceSize() const
223 {
224     return FloatSize(width(), height());
225 }
226
227 void ImageBitmap::trace(Visitor* visitor)
228 {
229     ImageLoaderClient::trace(visitor);
230 }
231
232 }