1/*
2 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
3 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4 * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
5 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "Image.h"
33
34#include "AffineTransform.h"
35#include "ImageObserver.h"
36#include "BitmapImage.h"
37#include "FloatRect.h"
38#include "PlatformString.h"
39#include "GraphicsContext.h"
40#include "StillImageQt.h"
41#include "qwebsettings.h"
42
43#include <QPixmap>
44#include <QPainter>
45#include <QImage>
46#include <QImageReader>
47#include <QTransform>
48
49#include <QDebug>
50
51#include <math.h>
52
53// This function loads resources into WebKit
54static QPixmap loadResourcePixmap(const char *name)
55{
56    QPixmap pixmap;
57    if (qstrcmp(name, "missingImage") == 0)
58        pixmap = QWebSettings::webGraphic(QWebSettings::MissingImageGraphic);
59    else if (qstrcmp(name, "nullPlugin") == 0)
60        pixmap = QWebSettings::webGraphic(QWebSettings::MissingPluginGraphic);
61    else if (qstrcmp(name, "urlIcon") == 0)
62        pixmap = QWebSettings::webGraphic(QWebSettings::DefaultFrameIconGraphic);
63    else if (qstrcmp(name, "textAreaResizeCorner") == 0)
64        pixmap = QWebSettings::webGraphic(QWebSettings::TextAreaSizeGripCornerGraphic);
65    else if (qstrcmp(name, "deleteButton") == 0)
66        pixmap = QWebSettings::webGraphic(QWebSettings::DeleteButtonGraphic);
67
68    return pixmap;
69}
70
71namespace WebCore {
72
73bool FrameData::clear(bool clearMetadata)
74{
75    if (clearMetadata)
76        m_haveMetadata = false;
77
78    if (m_frame) {
79        delete m_frame;
80        m_frame = 0;
81        return true;
82    }
83    return false;
84}
85
86
87// ================================================
88// Image Class
89// ================================================
90
91PassRefPtr<Image> Image::loadPlatformResource(const char* name)
92{
93    return StillImage::create(loadResourcePixmap(name));
94}
95
96void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
97                        const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
98{
99    QPixmap* framePixmap = nativeImageForCurrentFrame();
100    if (!framePixmap) // If it's too early we won't have an image yet.
101        return;
102
103    QPixmap pixmap = *framePixmap;
104    QRect tr = QRectF(tileRect).toRect();
105    if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height())
106        pixmap = pixmap.copy(tr);
107
108    QBrush b(pixmap);
109    b.setTransform(patternTransform);
110    ctxt->save();
111    ctxt->setCompositeOperation(op);
112    QPainter* p = ctxt->platformContext();
113    if (!pixmap.hasAlpha() && p->compositionMode() == QPainter::CompositionMode_SourceOver)
114        p->setCompositionMode(QPainter::CompositionMode_Source);
115    p->setBrushOrigin(phase);
116    p->fillRect(destRect, b);
117    ctxt->restore();
118
119    if (imageObserver())
120        imageObserver()->didDraw(this);
121}
122
123BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer)
124    : Image(observer)
125    , m_currentFrame(0)
126    , m_frames(0)
127    , m_frameTimer(0)
128    , m_repetitionCount(cAnimationNone)
129    , m_repetitionCountStatus(Unknown)
130    , m_repetitionsComplete(0)
131    , m_isSolidColor(false)
132    , m_checkedForSolidColor(false)
133    , m_animationFinished(true)
134    , m_allDataReceived(true)
135    , m_haveSize(true)
136    , m_sizeAvailable(true)
137    , m_decodedSize(0)
138    , m_haveFrameCount(true)
139    , m_frameCount(1)
140{
141    initPlatformData();
142
143    int width = pixmap->width();
144    int height = pixmap->height();
145    m_decodedSize = width * height * 4;
146    m_size = IntSize(width, height);
147
148    m_frames.grow(1);
149    m_frames[0].m_frame = pixmap;
150    m_frames[0].m_hasAlpha = pixmap->hasAlpha();
151    m_frames[0].m_haveMetadata = true;
152    checkForSolidColor();
153}
154
155void BitmapImage::initPlatformData()
156{
157}
158
159void BitmapImage::invalidatePlatformData()
160{
161}
162
163// Drawing Routines
164void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
165                       const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
166{
167    startAnimation();
168
169    QPixmap* image = nativeImageForCurrentFrame();
170    if (!image)
171        return;
172
173    if (mayFillWithSolidColor()) {
174        fillWithSolidColor(ctxt, dst, solidColor(), styleColorSpace, op);
175        return;
176    }
177
178    IntSize selfSize = size();
179
180    ctxt->save();
181
182    // Set the compositing operation.
183    ctxt->setCompositeOperation(op);
184
185    QPainter* painter(ctxt->platformContext());
186
187    if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver)
188        painter->setCompositionMode(QPainter::CompositionMode_Source);
189
190    // Test using example site at
191    // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html
192    painter->drawPixmap(dst, *image, src);
193
194    ctxt->restore();
195
196    if (imageObserver())
197        imageObserver()->didDraw(this);
198}
199
200void BitmapImage::checkForSolidColor()
201{
202    m_isSolidColor = false;
203    m_checkedForSolidColor = true;
204
205    if (frameCount() > 1)
206        return;
207
208    QPixmap* framePixmap = frameAtIndex(0);
209    if (!framePixmap || framePixmap->width() != 1 || framePixmap->height() != 1)
210        return;
211
212    m_isSolidColor = true;
213    m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0));
214}
215
216#if OS(WINDOWS)
217PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
218{
219    return BitmapImage::create(new QPixmap(QPixmap::fromWinHBITMAP(hBitmap)));
220}
221#endif
222
223}
224
225
226// vim: ts=4 sw=4 et
227