2 * Copyright 2009, The Android Open Source Project
3 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "TransformationMatrix.h"
29 #include "BitmapImage.h"
31 #include "FloatRect.h"
32 #include "GraphicsContext.h"
33 #include "PlatformGraphicsContext.h"
34 #include "PlatformString.h"
35 #include "SharedBuffer.h"
37 #include "android_graphics.h"
38 #include "SkBitmapRef.h"
40 #include "SkColorPriv.h"
41 #include "SkImageDecoder.h"
44 #include "SkTemplates.h"
46 #include <utils/AssetManager.h>
48 //#define TRACE_SUBSAMPLED_BITMAPS
49 //#define TRACE_SKIPPED_BITMAPS
51 android::AssetManager* globalAssetManager() {
52 static android::AssetManager* gGlobalAssetMgr;
53 if (!gGlobalAssetMgr) {
54 gGlobalAssetMgr = new android::AssetManager();
55 gGlobalAssetMgr->addDefaultAssets();
57 return gGlobalAssetMgr;
62 bool FrameData::clear(bool clearMetadata)
65 m_haveMetadata = false;
75 BitmapImage::BitmapImage(SkBitmapRef* ref, ImageObserver* observer)
80 , m_repetitionCount(0)
81 , m_repetitionsComplete(0)
82 , m_isSolidColor(false)
83 , m_animationFinished(true)
84 , m_allDataReceived(true)
86 , m_sizeAvailable(true)
88 , m_haveFrameCount(true)
93 m_size = IntSize(ref->bitmap().width(), ref->bitmap().height());
96 m_frames[0].m_frame = ref;
97 m_frames[0].m_hasAlpha = !ref->bitmap().isOpaque();
103 void BitmapImage::initPlatformData()
108 void BitmapImage::invalidatePlatformData()
112 void BitmapImage::checkForSolidColor()
114 m_isSolidColor = false;
115 if (frameCount() == 1) {
116 SkBitmapRef* ref = frameAtIndex(0);
118 return; // keep solid == false
121 const SkBitmap& bm = ref->bitmap();
122 if (bm.width() != 1 || bm.height() != 1) {
123 return; // keep solid == false
126 SkAutoLockPixels alp(bm);
127 if (!bm.readyToDraw()) {
128 return; // keep solid == false
132 switch (bm.getConfig()) {
133 case SkBitmap::kARGB_8888_Config:
134 color = *bm.getAddr32(0, 0);
136 case SkBitmap::kRGB_565_Config:
137 color = SkPixel16ToPixel32(*bm.getAddr16(0, 0));
139 case SkBitmap::kIndex8_Config: {
140 SkColorTable* ctable = bm.getColorTable();
144 color = (*ctable)[*bm.getAddr8(0, 0)];
148 return; // keep solid == false
150 m_isSolidColor = true;
151 m_solidColor = android_SkPMColorToWebCoreColor(color);
155 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect,
156 const FloatRect& srcRect, CompositeOperator compositeOp)
160 SkBitmapRef* image = this->nativeImageForCurrentFrame();
161 if (!image) { // If it's too early we won't have an image yet.
165 // in case we get called with an incomplete bitmap
166 const SkBitmap& bitmap = image->bitmap();
167 if (bitmap.getPixels() == NULL && bitmap.pixelRef() == NULL) {
168 #ifdef TRACE_SKIPPED_BITMAPS
169 SkDebugf("----- skip bitmapimage: [%d %d] pixels %p pixelref %p\n",
170 bitmap.width(), bitmap.height(),
171 bitmap.getPixels(), bitmap.pixelRef());
178 float invScaleX = (float)bitmap.width() / image->origWidth();
179 float invScaleY = (float)bitmap.height() / image->origHeight();
181 android_setrect(&dstR, dstRect);
182 android_setrect_scaled(&srcR, srcRect, invScaleX, invScaleY);
183 if (srcR.isEmpty() || dstR.isEmpty()) {
184 #ifdef TRACE_SKIPPED_BITMAPS
185 SkDebugf("----- skip bitmapimage: [%d %d] src-empty %d dst-empty %d\n",
186 bitmap.width(), bitmap.height(),
187 srcR.isEmpty(), dstR.isEmpty());
192 SkCanvas* canvas = ctxt->platformContext()->mCanvas;
195 paint.setFilterBitmap(true);
196 paint.setPorterDuffXfermode(android_convert_compositeOp(compositeOp));
197 canvas->drawBitmapRect(bitmap, &srcR, dstR, &paint);
199 #ifdef TRACE_SUBSAMPLED_BITMAPS
200 if (bitmap.width() != image->origWidth() ||
201 bitmap.height() != image->origHeight()) {
202 SkDebugf("--- BitmapImage::draw [%d %d] orig [%d %d]\n",
203 bitmap.width(), bitmap.height(),
204 image->origWidth(), image->origHeight());
209 void BitmapImage::setURL(const String& str)
211 m_source.setURL(str);
214 ///////////////////////////////////////////////////////////////////////////////
216 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect,
217 const TransformationMatrix& patternTransform,
218 const FloatPoint& phase, CompositeOperator compositeOp,
219 const FloatRect& destRect)
221 SkBitmapRef* image = this->nativeImageForCurrentFrame();
222 if (!image) { // If it's too early we won't have an image yet.
226 // in case we get called with an incomplete bitmap
227 const SkBitmap& origBitmap = image->bitmap();
228 if (origBitmap.getPixels() == NULL && origBitmap.pixelRef() == NULL) {
233 android_setrect(&dstR, destRect);
234 if (dstR.isEmpty()) {
238 // now extract the proper subset of the src image
241 if (!origBitmap.extractSubset(&bitmap, *android_setrect(&srcR, srcRect))) {
242 SkDebugf("--- Image::drawPattern calling extractSubset failed\n");
246 SkCanvas* canvas = ctxt->platformContext()->mCanvas;
249 SkShader* shader = SkShader::CreateBitmapShader(bitmap,
250 SkShader::kRepeat_TileMode,
251 SkShader::kRepeat_TileMode);
252 paint.setShader(shader)->unref();
253 // now paint is the only owner of shader
254 paint.setPorterDuffXfermode(android_convert_compositeOp(compositeOp));
255 paint.setFilterBitmap(true);
257 SkMatrix matrix(patternTransform);
259 float scaleX = (float)image->origWidth() / bitmap.width();
260 float scaleY = (float)image->origHeight() / bitmap.height();
261 matrix.preScale(SkFloatToScalar(scaleX), SkFloatToScalar(scaleY));
263 matrix.postTranslate(SkFloatToScalar(phase.x()),
264 SkFloatToScalar(phase.y()));
265 shader->setLocalMatrix(matrix);
266 canvas->drawRect(dstR, paint);
268 #ifdef TRACE_SUBSAMPLED_BITMAPS
269 if (bitmap.width() != image->origWidth() ||
270 bitmap.height() != image->origHeight()) {
271 SkDebugf("--- Image::drawPattern [%d %d] orig [%d %d] dst [%g %g]\n",
272 bitmap.width(), bitmap.height(),
273 image->origWidth(), image->origHeight(),
274 SkScalarToFloat(dstR.width()), SkScalarToFloat(dstR.height()));
279 // missingImage, textAreaResizeCorner
280 PassRefPtr<Image> Image::loadPlatformResource(const char *name)
282 android::AssetManager* am = globalAssetManager();
284 SkString path("webkit/");
288 android::Asset* a = am->open(path.c_str(),
289 android::Asset::ACCESS_BUFFER);
291 SkDebugf("---------------- failed to open image asset %s\n", name);
295 SkAutoTDelete<android::Asset> ad(a);
298 if (SkImageDecoder::DecodeMemory(a->getBuffer(false), a->getLength(), &bm)) {
299 SkBitmapRef* ref = new SkBitmapRef(bm);
300 // create will call ref(), so we need aur() to release ours upon return
301 SkAutoUnref aur(ref);
302 return BitmapImage::create(ref, 0);
304 return Image::nullImage();