1/*
2 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3 * Copyright (C) 2007-2009 Torch Mobile Inc.
4 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "Image.h"
29
30#include "BitmapImage.h"
31#include "GraphicsContext.h"
32#include "ImageDecoder.h"
33#include "NotImplemented.h"
34#include "PlatformString.h"
35#include "SharedBuffer.h"
36#include "TransformationMatrix.h"
37#include "WinceGraphicsExtras.h"
38#include <wtf/OwnPtr.h>
39
40#include <windows.h>
41
42namespace WebCore {
43
44NativeImagePtr ImageFrame::asNewNativeImage() const
45{
46    return SharedBitmap::create(m_backingStore, m_size, hasAlpha());
47}
48
49bool FrameData::clear(bool clearMetaData)
50{
51    if (clearMetaData)
52        m_haveMetadata = false;
53
54    if (m_frame) {
55        m_frame = 0;
56        return true;
57    }
58
59    return false;
60}
61
62bool BitmapImage::getHBITMAPOfSize(HBITMAP bmp, LPSIZE size)
63{
64    if (!bmp)
65        return false;
66
67    BITMAP bmpInfo;
68    GetObject(bmp, sizeof(BITMAP), &bmpInfo);
69
70    ASSERT(bmpInfo.bmBitsPixel == 32);
71    int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
72
73    OwnPtr<HDC> hdc(CreateCompatibleDC(0));
74    HGDIOBJ hOldBmp = SelectObject(hdc.get(), bmp);
75
76    {
77        GraphicsContext gc(hdc.get());
78
79        IntSize imageSize = BitmapImage::size();
80        if (size)
81            drawFrameMatchingSourceSize(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), IntSize(*size), ColorSpaceDeviceRGB, CompositeCopy);
82        else
83            draw(&gc, FloatRect(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight), FloatRect(0, 0, imageSize.width(), imageSize.height()), ColorSpaceDeviceRGB, CompositeCopy);
84    }
85
86    SelectObject(hdc.get(), hOldBmp);
87
88    return true;
89}
90
91void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext* ctxt, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator compositeOp)
92{
93    int frames = frameCount();
94    for (int i = 0; i < frames; ++i) {
95        RefPtr<SharedBitmap> bmp = frameAtIndex(i);
96        if (!bmp || bmp->height() != static_cast<unsigned>(srcSize.height()) || bmp->width() != static_cast<unsigned>(srcSize.width()))
97            continue;
98
99        size_t currentFrame = m_currentFrame;
100        m_currentFrame = i;
101        draw(ctxt, dstRect, FloatRect(0, 0, srcSize.width(), srcSize.height()), styleColorSpace, compositeOp);
102        m_currentFrame = currentFrame;
103        return;
104    }
105
106    // No image of the correct size was found, fallback to drawing the current frame
107    IntSize imageSize = BitmapImage::size();
108    draw(ctxt, dstRect, FloatRect(0, 0, imageSize.width(), imageSize.height()), styleColorSpace, compositeOp);
109}
110
111void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRectIn, ColorSpace styleColorSpace, CompositeOperator compositeOp)
112{
113    if (!m_source.initialized())
114        return;
115
116    if (mayFillWithSolidColor())
117        fillWithSolidColor(ctxt, dstRect, solidColor(), styleColorSpace, compositeOp);
118    else {
119        IntRect intSrcRect(srcRectIn);
120        RefPtr<SharedBitmap> bmp = frameAtIndex(m_currentFrame);
121
122        if (bmp->width() != m_source.size().width()) {
123            double scaleFactor = static_cast<double>(bmp->width()) / m_source.size().width();
124
125            intSrcRect.setX(stableRound(srcRectIn.x() * scaleFactor));
126            intSrcRect.setWidth(stableRound(srcRectIn.width() * scaleFactor));
127            intSrcRect.setY(stableRound(srcRectIn.y() * scaleFactor));
128            intSrcRect.setHeight(stableRound(srcRectIn.height() * scaleFactor));
129        }
130        bmp->draw(ctxt, enclosingIntRect(dstRect), intSrcRect, styleColorSpace, compositeOp);
131    }
132
133    startAnimation();
134}
135
136void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
137                        const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
138{
139    notImplemented();
140}
141
142void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
143                        const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
144{
145    RefPtr<SharedBitmap> bmp = nativeImageForCurrentFrame();
146    if (!bmp)
147        return;
148
149    bmp->drawPattern(ctxt, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, m_source.size());
150}
151
152void BitmapImage::checkForSolidColor()
153{
154    if (m_checkedForSolidColor)
155        return;
156
157    if (frameCount() != 1) {
158        m_isSolidColor = false;
159        m_checkedForSolidColor = true;
160        return;
161    }
162
163    RefPtr<SharedBitmap> bmp = frameAtIndex(0);
164    if (!bmp || !bmp->validHeight()) {
165        m_isSolidColor = false;
166        return;
167    }
168
169    if (bmp->width() != 1 || bmp->validHeight() != 1) {
170        m_isSolidColor = false;
171        m_checkedForSolidColor = true;
172        return;
173    }
174
175    m_isSolidColor = true;
176
177    if (bmp->is16bit()) {
178        unsigned short c = ((unsigned short *)bmp->bytes())[0];
179        int r = (c >> 7) & 0xF8;
180        int g = (c >> 2) & 0xF8;
181        int b = (c << 3) & 0xF8;
182        if (bmp->usesTransparentColor() && bmp->transparentColor() == RGB(r, g, b))
183            m_solidColor = Color(r, g, b, 0);
184        else
185            m_solidColor = Color(r, g, b);
186    } else {
187        unsigned c = ((unsigned *)bmp->bytes())[0];
188        m_solidColor = Color(c);
189    }
190
191    if (bmp->validHeight() == bmp->height())
192        m_checkedForSolidColor = true;
193}
194
195} // namespace WebCore
196