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