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 "SharedBuffer.h"
35#include "TransformationMatrix.h"
36#include "WinceGraphicsExtras.h"
37#include <wtf/OwnPtr.h>
38#include <wtf/text/WTFString.h>
39
40#include <windows.h>
41
42namespace WebCore {
43
44PassNativeImagePtr 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 = adoptPtr(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, BlendModeNormal);
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, BlendModeNormal);
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, BlendModeNormal);
109}
110
111void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRectIn, ColorSpace styleColorSpace, CompositeOperator compositeOp, BlendMode blendMode)
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        if (bmp) {
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, blendMode);
131        }
132    }
133
134    startAnimation();
135}
136
137void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
138    const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
139{
140    notImplemented();
141}
142
143void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform,
144                        const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
145{
146    RefPtr<SharedBitmap> bmp = nativeImageForCurrentFrame();
147    if (!bmp)
148        return;
149
150    bmp->drawPattern(ctxt, tileRectIn, patternTransform, phase, styleColorSpace, op, destRect, m_source.size());
151}
152
153void BitmapImage::checkForSolidColor()
154{
155    if (m_checkedForSolidColor)
156        return;
157
158    if (frameCount() != 1) {
159        m_isSolidColor = false;
160        m_checkedForSolidColor = true;
161        return;
162    }
163
164    RefPtr<SharedBitmap> bmp = frameAtIndex(0);
165    if (!bmp || !bmp->validHeight()) {
166        m_isSolidColor = false;
167        return;
168    }
169
170    if (bmp->width() != 1 || bmp->validHeight() != 1) {
171        m_isSolidColor = false;
172        m_checkedForSolidColor = true;
173        return;
174    }
175
176    m_isSolidColor = true;
177
178    if (bmp->is16bit()) {
179        unsigned short c = ((unsigned short *)bmp->bytes())[0];
180        int r = (c >> 7) & 0xF8;
181        int g = (c >> 2) & 0xF8;
182        int b = (c << 3) & 0xF8;
183        if (bmp->usesTransparentColor() && bmp->transparentColor() == RGB(r, g, b))
184            m_solidColor = Color(r, g, b, 0);
185        else
186            m_solidColor = Color(r, g, b);
187    } else {
188        unsigned c = ((unsigned *)bmp->bytes())[0];
189        m_solidColor = Color(c);
190    }
191
192    if (bmp->validHeight() == bmp->height())
193        m_checkedForSolidColor = true;
194}
195
196} // namespace WebCore
197