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.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
35 #include "AffineTransform.h"
36 #include "BitmapImage.h"
37 #include "FloatRect.h"
38 #include "GraphicsContext.h"
39 #include "ImageObserver.h"
40 #include "PlatformString.h"
41 #include "ShadowBlur.h"
42 #include "StillImageQt.h"
43 #include "qwebsettings.h"
45 #include <QApplication>
48 #include <QImageReader>
56 typedef QHash<QByteArray, QPixmap> WebGraphicHash;
57 Q_GLOBAL_STATIC(WebGraphicHash, _graphics)
59 static void earlyClearGraphics()
64 static WebGraphicHash* graphics()
66 WebGraphicHash* hash = _graphics();
68 if (hash->isEmpty()) {
70 // prevent ~QPixmap running after ~QApplication (leaks native pixmaps)
71 qAddPostRoutine(earlyClearGraphics);
73 // QWebSettings::MissingImageGraphic
74 hash->insert("missingImage", QPixmap(QLatin1String(":webkit/resources/missingImage.png")));
75 // QWebSettings::MissingPluginGraphic
76 hash->insert("nullPlugin", QPixmap(QLatin1String(":webkit/resources/nullPlugin.png")));
77 // QWebSettings::DefaultFrameIconGraphic
78 hash->insert("urlIcon", QPixmap(QLatin1String(":webkit/resources/urlIcon.png")));
79 // QWebSettings::TextAreaSizeGripCornerGraphic
80 hash->insert("textAreaResizeCorner", QPixmap(QLatin1String(":webkit/resources/textAreaResizeCorner.png")));
81 // QWebSettings::DeleteButtonGraphic
82 hash->insert("deleteButton", QPixmap(QLatin1String(":webkit/resources/deleteButton.png")));
83 // QWebSettings::InputSpeechButtonGraphic
84 hash->insert("inputSpeech", QPixmap(QLatin1String(":webkit/resources/inputSpeech.png")));
85 // QWebSettings::SearchCancelButtonGraphic
86 hash->insert("searchCancelButton", QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton));
87 // QWebSettings::SearchCancelButtonPressedGraphic
88 hash->insert("searchCancelButtonPressed", QApplication::style()->standardPixmap(QStyle::SP_DialogCloseButton));
94 // This function loads resources into WebKit
95 static QPixmap loadResourcePixmap(const char *name)
97 return graphics()->value(name);
102 bool FrameData::clear(bool clearMetadata)
105 m_haveMetadata = false;
116 // ================================================
118 // ================================================
120 PassRefPtr<Image> Image::loadPlatformResource(const char* name)
122 return StillImage::create(loadResourcePixmap(name));
125 void Image::setPlatformResource(const char* name, const QPixmap& pixmap)
127 WebGraphicHash* h = graphics();
131 h->insert(name, pixmap);
134 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
135 const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect)
137 QPixmap* framePixmap = nativeImageForCurrentFrame();
138 if (!framePixmap) // If it's too early we won't have an image yet.
141 // Qt interprets 0 width/height as full width/height so just short circuit.
142 QRectF dr = QRectF(destRect).normalized();
143 QRect tr = QRectF(tileRect).toRect().normalized();
144 if (!dr.width() || !dr.height() || !tr.width() || !tr.height())
147 QPixmap pixmap = *framePixmap;
148 if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height())
149 pixmap = pixmap.copy(tr);
151 CompositeOperator previousOperator = ctxt->compositeOperation();
153 ctxt->setCompositeOperation(!pixmap.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
155 QPainter* p = ctxt->platformContext();
156 QTransform transform(patternTransform);
158 // If this would draw more than one scaled tile, we scale the pixmap first and then use the result to draw.
159 if (transform.type() == QTransform::TxScale) {
160 QRectF tileRectInTargetCoords = (transform * QTransform().translate(phase.x(), phase.y())).mapRect(tr);
162 bool tileWillBePaintedOnlyOnce = tileRectInTargetCoords.contains(dr);
163 if (!tileWillBePaintedOnlyOnce) {
164 QSizeF scaledSize(float(pixmap.width()) * transform.m11(), float(pixmap.height()) * transform.m22());
165 QPixmap scaledPixmap(scaledSize.toSize());
166 if (pixmap.hasAlpha())
167 scaledPixmap.fill(Qt::transparent);
169 QPainter painter(&scaledPixmap);
170 painter.setCompositionMode(QPainter::CompositionMode_Source);
171 painter.setRenderHints(p->renderHints());
172 painter.drawPixmap(QRect(0, 0, scaledPixmap.width(), scaledPixmap.height()), pixmap);
174 pixmap = scaledPixmap;
175 transform = QTransform::fromTranslate(transform.dx(), transform.dy());
179 /* Translate the coordinates as phase is not in world matrix coordinate space but the tile rect origin is. */
180 transform *= QTransform().translate(phase.x(), phase.y());
181 transform.translate(tr.x(), tr.y());
184 b.setTransform(transform);
187 ctxt->setCompositeOperation(previousOperator);
190 imageObserver()->didDraw(this);
193 BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer)
198 , m_repetitionCount(cAnimationNone)
199 , m_repetitionCountStatus(Unknown)
200 , m_repetitionsComplete(0)
201 , m_isSolidColor(false)
202 , m_checkedForSolidColor(false)
203 , m_animationFinished(true)
204 , m_allDataReceived(true)
206 , m_sizeAvailable(true)
208 , m_haveFrameCount(true)
213 int width = pixmap->width();
214 int height = pixmap->height();
215 m_decodedSize = width * height * 4;
216 m_size = IntSize(width, height);
219 m_frames[0].m_frame = pixmap;
220 m_frames[0].m_hasAlpha = pixmap->hasAlpha();
221 m_frames[0].m_haveMetadata = true;
222 checkForSolidColor();
225 void BitmapImage::initPlatformData()
229 void BitmapImage::invalidatePlatformData()
234 void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
235 const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op)
237 QRectF normalizedDst = dst.normalized();
238 QRectF normalizedSrc = src.normalized();
242 if (normalizedSrc.isEmpty() || normalizedDst.isEmpty())
245 QPixmap* image = nativeImageForCurrentFrame();
249 if (mayFillWithSolidColor()) {
250 fillWithSolidColor(ctxt, normalizedDst, solidColor(), styleColorSpace, op);
254 CompositeOperator previousOperator = ctxt->compositeOperation();
255 ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
257 if (ctxt->hasShadow()) {
258 ShadowBlur* shadow = ctxt->shadowBlur();
259 GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst);
261 QPainter* shadowPainter = shadowContext->platformContext();
262 shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc);
263 shadow->endShadowLayer(ctxt);
267 ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc);
269 ctxt->setCompositeOperation(previousOperator);
272 imageObserver()->didDraw(this);
275 void BitmapImage::checkForSolidColor()
277 m_isSolidColor = false;
278 m_checkedForSolidColor = true;
280 if (frameCount() > 1)
283 QPixmap* framePixmap = frameAtIndex(0);
284 if (!framePixmap || framePixmap->width() != 1 || framePixmap->height() != 1)
287 m_isSolidColor = true;
288 m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0));
292 PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap)
294 return BitmapImage::create(new QPixmap(QPixmap::fromWinHBITMAP(hBitmap)));