• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "BitmapImage.h"
28 #include "ImageBuffer.h"
29 #include "ImageData.h"
30 #include "NotImplemented.h"
31 
32 #include "android_graphics.h"
33 #include "GraphicsContext.h"
34 #include "PlatformGraphicsContext.h"
35 #include "SkBitmapRef.h"
36 #include "SkCanvas.h"
37 #include "SkColorPriv.h"
38 #include "SkDevice.h"
39 #include "SkUnPreMultiply.h"
40 
41 using namespace std;
42 
43 namespace WebCore {
44 
ImageBufferData(const IntSize &)45 ImageBufferData::ImageBufferData(const IntSize&)
46 {
47 }
48 
ImageBuffer(const IntSize & size,bool grayScale,bool & success)49 ImageBuffer::ImageBuffer(const IntSize& size, bool grayScale, bool& success)
50     : m_data(size)
51     , m_size(size)
52 {
53     m_context.set(GraphicsContext::createOffscreenContext(size.width(), size.height()));
54     success = true;
55 }
56 
~ImageBuffer()57 ImageBuffer::~ImageBuffer()
58 {
59 }
60 
context() const61 GraphicsContext* ImageBuffer::context() const
62 {
63     return m_context.get();
64 }
65 
66 /*  This guy needs to make a deep copy of the bitmap, so that the returned
67     image doesn't reflect any subsequent changes to the canvas' backend.
68     e.g. this is called when <canvas> wants to make a Pattern, which needs
69     to snapshot the current pixels when it is created.
70  */
image() const71 Image* ImageBuffer::image() const
72 {
73     if (!m_image) {
74         ASSERT(context());
75         SkCanvas* canvas = context()->platformContext()->mCanvas;
76         SkDevice* device = canvas->getDevice();
77         const SkBitmap& orig = device->accessBitmap(false);
78 
79         SkBitmap copy;
80         orig.copyTo(&copy, orig.config());
81 
82         SkBitmapRef* ref = new SkBitmapRef(copy);
83         m_image = BitmapImage::create(ref, 0);
84         ref->unref();
85     }
86     return m_image.get();
87 }
88 
getImageData(const IntRect & rect) const89 PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
90 {
91     GraphicsContext* gc = this->context();
92     if (!gc) {
93         return 0;
94     }
95 
96     const SkBitmap& src = android_gc2canvas(gc)->getDevice()->accessBitmap(false);
97     SkAutoLockPixels alp(src);
98     if (!src.getPixels()) {
99         return 0;
100     }
101 
102     // ! Can't use PassRefPtr<>, otherwise the second access will cause crash.
103     RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
104     unsigned char* data = result->data()->data()->data();
105 
106     if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
107         memset(data, 0, result->data()->length());
108 
109     int originx = rect.x();
110     int destx = 0;
111     if (originx < 0) {
112         destx = -originx;
113         originx = 0;
114     }
115     int endx = rect.x() + rect.width();
116     if (endx > m_size.width())
117         endx = m_size.width();
118     int numColumns = endx - originx;
119 
120     int originy = rect.y();
121     int desty = 0;
122     if (originy < 0) {
123         desty = -originy;
124         originy = 0;
125     }
126     int endy = rect.y() + rect.height();
127     if (endy > m_size.height())
128         endy = m_size.height();
129     int numRows = endy - originy;
130 
131     unsigned srcPixelsPerRow = src.rowBytesAsPixels();
132     unsigned destBytesPerRow = 4 * rect.width();
133 
134     const SkPMColor* srcRows = src.getAddr32(originx, originy);
135     unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
136     for (int y = 0; y < numRows; ++y) {
137         for (int x = 0; x < numColumns; x++) {
138             // ugh, it appears they want unpremultiplied pixels
139             SkColor c = SkUnPreMultiply::PMColorToColor(srcRows[x]);
140             int basex = x * 4;
141             destRows[basex + 0] = SkColorGetR(c);
142             destRows[basex + 1] = SkColorGetG(c);
143             destRows[basex + 2] = SkColorGetB(c);
144             destRows[basex + 3] = SkColorGetA(c);
145         }
146         srcRows += srcPixelsPerRow;
147         destRows += destBytesPerRow;
148     }
149     return result;
150 }
151 
putImageData(ImageData * source,const IntRect & sourceRect,const IntPoint & destPoint)152 void ImageBuffer::putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
153 {
154     GraphicsContext* gc = this->context();
155     if (!gc) {
156         return;
157     }
158 
159     const SkBitmap& dst = android_gc2canvas(gc)->getDevice()->accessBitmap(true);
160     SkAutoLockPixels alp(dst);
161     if (!dst.getPixels()) {
162         return;
163     }
164 
165     ASSERT(sourceRect.width() > 0);
166     ASSERT(sourceRect.height() > 0);
167 
168     int originx = sourceRect.x();
169     int destx = destPoint.x() + sourceRect.x();
170     ASSERT(destx >= 0);
171     ASSERT(destx < m_size.width());
172     ASSERT(originx >= 0);
173     ASSERT(originx <= sourceRect.right());
174 
175     int endx = destPoint.x() + sourceRect.right();
176     ASSERT(endx <= m_size.width());
177 
178     int numColumns = endx - destx;
179 
180     int originy = sourceRect.y();
181     int desty = destPoint.y() + sourceRect.y();
182     ASSERT(desty >= 0);
183     ASSERT(desty < m_size.height());
184     ASSERT(originy >= 0);
185     ASSERT(originy <= sourceRect.bottom());
186 
187     int endy = destPoint.y() + sourceRect.bottom();
188     ASSERT(endy <= m_size.height());
189     int numRows = endy - desty;
190 
191     unsigned srcBytesPerRow = 4 * source->width();
192     unsigned dstPixelsPerRow = dst.rowBytesAsPixels();
193 
194     unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
195     SkPMColor* dstRows = dst.getAddr32(destx, desty);
196     for (int y = 0; y < numRows; ++y) {
197         for (int x = 0; x < numColumns; x++) {
198             int basex = x * 4;
199             dstRows[x] = SkPackARGB32(srcRows[basex + 3],
200                                       srcRows[basex + 0],
201                                       srcRows[basex + 1],
202                                       srcRows[basex + 2]);
203         }
204         dstRows += dstPixelsPerRow;
205         srcRows += srcBytesPerRow;
206     }
207 }
208 
209 
toDataURL(const String &) const210 String ImageBuffer::toDataURL(const String&) const
211 {
212     // leaving this unimplemented, until I understand what its for (and what it
213     // really is).
214     return "data:,";    // I think this means we couldn't make the data url
215 }
216 
217 }
218