1231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block/*
2231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
6231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2008 Andrea Anzani <andrea.anzani@gmail.com>
78a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
8231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
9231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * All rights reserved.
10231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
11231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Redistribution and use in source and binary forms, with or without
12231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * modification, are permitted provided that the following conditions
13231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * are met:
14231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 1. Redistributions of source code must retain the above copyright
15231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    notice, this list of conditions and the following disclaimer.
16231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 2. Redistributions in binary form must reproduce the above copyright
17231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    notice, this list of conditions and the following disclaimer in the
18231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *    documentation and/or other materials provided with the distribution.
19231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
20231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block */
32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "config.h"
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Image.h"
35231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "BitmapImage.h"
37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "FloatRect.h"
38231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "GraphicsContext.h"
398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "ImageObserver.h"
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "NotImplemented.h"
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "PlatformString.h"
42dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SharedBuffer.h"
438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#include "TransformationMatrix.h"
44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <Application.h>
45231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <Bitmap.h>
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <View.h>
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// This function loads resources from WebKit
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockVector<char> loadResourceIntoArray(const char*);
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocknamespace WebCore {
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockbool FrameData::clear(bool clearMetadata)
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (clearMetadata)
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_haveMetadata = false;
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_frame) {
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        delete m_frame;
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_frame = 0;
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_duration = 0.0f;
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_hasAlpha = true;
64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return false;
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockWTF::PassRefPtr<Image> Image::loadPlatformResource(const char* name)
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Vector<char> array = loadResourceIntoArray(name);
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    WTF::PassRefPtr<BitmapImage> image = BitmapImage::create();
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<SharedBuffer> buffer = SharedBuffer::create(array.data(), array.size());
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    image->setData(buffer, true);
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return image;
78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid BitmapImage::initPlatformData()
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid BitmapImage::invalidatePlatformData()
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Drawing Routines
89643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
918a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!m_source.initialized())
928a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return;
938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
948a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // Spin the animation to the correct frame before we try to draw it, so we
958a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // don't draw an old frame and then immediately need to draw a newer one,
968a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // causing flicker and wasting CPU.
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    startAnimation();
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    BBitmap* image = nativeImageForCurrentFrame();
100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!image || !image->IsValid()) // If the image hasn't fully loaded.
101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (mayFillWithSolidColor()) {
104643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ctxt->save();
109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ctxt->setCompositeOperation(op);
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    BRect srcRect(src);
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    BRect dstRect(dst);
113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Test using example site at
115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ctxt->platformContext()->SetDrawingMode(B_OP_ALPHA);
1178a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    ctxt->platformContext()->DrawBitmapAsync(image, srcRect, dstRect);
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ctxt->restore();
1198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1208a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (imageObserver())
1218a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        imageObserver()->didDraw(this);
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
124dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& dstRect)
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    BBitmap* image = nativeImageForCurrentFrame();
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!image || !image->IsValid()) // If the image hasn't fully loaded.
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1308a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // Figure out if the image has any alpha transparency, we can use faster drawing if not
1318a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    bool hasAlpha = false;
1328a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1338a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    uint8* bits = reinterpret_cast<uint8*>(image->Bits());
1348a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    uint32 width = image->Bounds().IntegerWidth() + 1;
1358a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    uint32 height = image->Bounds().IntegerHeight() + 1;
1368a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1378a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    uint32 bytesPerRow = image->BytesPerRow();
1388a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    for (uint32 y = 0; y < height && !hasAlpha; y++) {
1398a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        uint8* p = bits;
1408a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        for (uint32 x = 0; x < width && !hasAlpha; x++) {
1418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            hasAlpha = p[3] < 255;
1428a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            p += 4;
1438a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        }
1448a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        bits += bytesPerRow;
1458a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    context->save();
1488a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (hasAlpha)
1498a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        context->platformContext()->SetDrawingMode(B_OP_ALPHA);
1508a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    else
1518a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        context->platformContext()->SetDrawingMode(B_OP_COPY);
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    context->clip(enclosingIntRect(dstRect));
1538a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    float currentW = phase.x();
1548a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    BRect bTileRect(tileRect);
1558a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    while (currentW < dstRect.x() + dstRect.width()) {
1568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        float currentH = phase.y();
1578a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        while (currentH < dstRect.y() + dstRect.height()) {
1588a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            BRect bDstRect(currentW, currentH, currentW + width - 1, currentH + height - 1);
1598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            context->platformContext()->DrawBitmapAsync(image, bTileRect, bDstRect);
1608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            currentH += height;
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
1628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        currentW += width;
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    context->restore();
1658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1668a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (imageObserver())
1678a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        imageObserver()->didDraw(this);
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid BitmapImage::checkForSolidColor()
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_isSolidColor = false;
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_checkedForSolidColor = true;
1748a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1758a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (frameCount() > 1)
1768a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return;
1778a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1788a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    BBitmap* image = getBBitmap();
1798a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!image || !image->Bounds().IsValid()
1808a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        || image->Bounds().IntegerWidth() > 0 || image->Bounds().IntegerHeight() > 0) {
1818a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        return;
1828a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
1838a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
1848a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    m_isSolidColor = true;
1858a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    uint8* bits = reinterpret_cast<uint8*>(image->Bits());
1868a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    m_solidColor = Color(bits[2], bits[1], bits[0], bits[3]);
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockBBitmap* BitmapImage::getBBitmap() const
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return const_cast<BitmapImage*>(this)->frameAtIndex(0);
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} // namespace WebCore
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
196