| Differences between
and this patch
- a/Source/WebCore/ChangeLog +80 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2016-07-12  Said Abou-Hallawa  <sabouhallawa@apple.com>
2
3
        Split the pixel data of ImageFrame to a separate class
4
        https://bugs.webkit.org/show_bug.cgi?id=159679
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Move the pixel data manipulation part in ImageFrame into a separate class
9
        and then make it optional (allocated on demand).
10
11
        * CMakeLists.txt:
12
        * PlatformEfl.cmake:
13
        * PlatformGTK.cmake:
14
        * PlatformWinCairo.cmake:
15
        * WebCore.xcodeproj/project.pbxproj:
16
        * platform/graphics/BitmapPixels.h: Added.
17
        (WebCore::BitmapPixels::create):
18
        (WebCore::BitmapPixels::BitmapPixels):
19
        (WebCore::BitmapPixels::width):
20
        (WebCore::BitmapPixels::height):
21
        (WebCore::BitmapPixels::setSize):
22
        (WebCore::BitmapPixels::at):
23
        (WebCore::BitmapPixels::clear):
24
        (WebCore::BitmapPixels::clearRect):
25
        (WebCore::BitmapPixels::repeatFirstRow):
26
        (WebCore::BitmapPixels::setRGBA):
27
        (WebCore::BitmapPixels::overRGBA):
28
        (WebCore::BitmapPixels::inBounds):
29
        * platform/graphics/Color.cpp:
30
        (WebCore::multiply255):
31
        (WebCore::divide255):
32
        (WebCore::divideCeil):
33
        (WebCore::premultipliedChannel):
34
        (WebCore::unpremultipliedChannel):
35
        (WebCore::makePremultipliedRGBA):
36
        (WebCore::makeUnPremultipliedRGBA):
37
        * platform/graphics/Color.h:
38
        * platform/graphics/ImageFrameData.h:
39
        (WebCore::ImageFrameData::pixels):
40
        (WebCore::ImageFrameData::hasPixels):
41
        * platform/image-decoders/ImageDecoder.cpp:
42
        (WebCore::ImageFrame::operator=):
43
        (WebCore::ImageFrame::clearPixelData):
44
        (WebCore::ImageFrame::zeroFillPixelData):
45
        (WebCore::ImageFrame::zeroFillFrameRect):
46
        (WebCore::ImageFrame::copyBitmapData):
47
        (WebCore::ImageFrame::setSize):
48
        (WebCore::ImageFrame::copyRowNTimes):
49
        * platform/image-decoders/ImageDecoder.h:
50
        (WebCore::ImageFrame::asNewNativeImage):
51
        (WebCore::ImageFrame::setRGBA):
52
        (WebCore::ImageFrame::getAddr):
53
        (WebCore::ImageFrame::hasPixelData):
54
        (WebCore::ImageFrame::overRGBA):
55
        (WebCore::ImageFrame::width):
56
        (WebCore::ImageFrame::height):
57
        (WebCore::ImageFrame::copyRowNTimes): Deleted.
58
        (WebCore::ImageFrame::fixPointUnsignedMultiply): Deleted.
59
        (WebCore::ImageFrame::divide255): Deleted.
60
        * platform/image-decoders/bmp/BMPImageReader.cpp:
61
        (WebCore::BMPImageReader::decodeBMP):
62
        * platform/image-decoders/cairo/BitmapPixelsCairo.cpp: Renamed from Source/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp.
63
        (WebCore::BitmapPixels::image):
64
        * platform/image-decoders/gif/GIFImageDecoder.cpp:
65
        (WebCore::GIFImageDecoder::haveDecodedRow):
66
        (WebCore::GIFImageDecoder::frameComplete):
67
        (WebCore::GIFImageDecoder::initFrameBuffer):
68
        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
69
        (WebCore::setPixel):
70
        (WebCore::JPEGImageDecoder::outputScanlines):
71
        * platform/image-decoders/png/PNGImageDecoder.cpp:
72
        (WebCore::setPixelRGB):
73
        (WebCore::setPixelRGBA):
74
        (WebCore::setPixelPremultipliedRGBA):
75
        (WebCore::PNGImageDecoder::rowAvailable):
76
        (WebCore::PNGImageDecoder::initFrameBuffer):
77
        (WebCore::PNGImageDecoder::frameComplete):
78
        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
79
        (WebCore::WEBPImageDecoder::decode):
80
1
2016-07-11  Said Abou-Hallawa  <sabouhallawa@apple,com>
81
2016-07-11  Said Abou-Hallawa  <sabouhallawa@apple,com>
2
82
3
        Rename FrameData to ImageFrameData and move it to a separate file
83
        Rename FrameData to ImageFrameData and move it to a separate file
- a/Source/WebCore/PlatformEfl.cmake -2 / +2 lines
Lines 179-187 list(APPEND WebCore_SOURCES a/Source/WebCore/PlatformEfl.cmake_sec1
179
    platform/graphics/x11/PlatformDisplayX11.cpp
179
    platform/graphics/x11/PlatformDisplayX11.cpp
180
    platform/graphics/x11/XUniqueResource.cpp
180
    platform/graphics/x11/XUniqueResource.cpp
181
181
182
    platform/image-encoders/JPEGImageEncoder.cpp
182
    platform/image-decoders/cairo/BitmapPixelsCairo.cpp
183
183
184
    platform/image-decoders/cairo/ImageDecoderCairo.cpp
184
    platform/image-encoders/JPEGImageEncoder.cpp
185
185
186
    platform/network/efl/NetworkStateNotifierEfl.cpp
186
    platform/network/efl/NetworkStateNotifierEfl.cpp
187
187
- a/Source/WebCore/PlatformGTK.cmake -1 / +1 lines
Lines 149-155 list(APPEND WebCore_SOURCES a/Source/WebCore/PlatformGTK.cmake_sec1
149
    platform/gtk/TemporaryLinkStubs.cpp
149
    platform/gtk/TemporaryLinkStubs.cpp
150
    platform/gtk/UserAgentGtk.cpp
150
    platform/gtk/UserAgentGtk.cpp
151
151
152
    platform/image-decoders/cairo/ImageDecoderCairo.cpp
152
    platform/image-decoders/cairo/BitmapPixelsCairo.cpp
153
153
154
    platform/mediastream/gtk/SDPProcessorScriptResourceGtk.cpp
154
    platform/mediastream/gtk/SDPProcessorScriptResourceGtk.cpp
155
155
- a/Source/WebCore/PlatformWinCairo.cmake -1 / +1 lines
Lines 46-52 list(APPEND WebCore_SOURCES a/Source/WebCore/PlatformWinCairo.cmake_sec1
46
    platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp
46
    platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp
47
    platform/graphics/win/SimpleFontDataCairoWin.cpp
47
    platform/graphics/win/SimpleFontDataCairoWin.cpp
48
48
49
    platform/image-decoders/cairo/ImageDecoderCairo.cpp
49
    platform/image-decoders/cairo/BitmapPixelsCairo.cpp
50
50
51
    platform/network/NetworkStorageSessionStub.cpp
51
    platform/network/NetworkStorageSessionStub.cpp
52
52
- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +4 lines
Lines 2325-2330 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
2325
		53ED3FDF167A88E7006762E6 /* JSInternalSettingsGenerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */; };
2325
		53ED3FDF167A88E7006762E6 /* JSInternalSettingsGenerated.h in Headers */ = {isa = PBXBuildFile; fileRef = 53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */; };
2326
		53EF766B16530A61004CBE49 /* SettingsMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EF766A16530A61004CBE49 /* SettingsMacros.h */; };
2326
		53EF766B16530A61004CBE49 /* SettingsMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EF766A16530A61004CBE49 /* SettingsMacros.h */; };
2327
		53EF766C16531994004CBE49 /* SettingsMacros.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 53EF766A16530A61004CBE49 /* SettingsMacros.h */; };
2327
		53EF766C16531994004CBE49 /* SettingsMacros.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 53EF766A16530A61004CBE49 /* SettingsMacros.h */; };
2328
		5504E4CB1D3557B200FE5088 /* BitmapPixels.h in Headers */ = {isa = PBXBuildFile; fileRef = 5504E4CA1D35532D00FE5088 /* BitmapPixels.h */; settings = {ATTRIBUTES = (Private, ); }; };
2328
		550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 550A0BC7085F6039007353D6 /* QualifiedName.cpp */; };
2329
		550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 550A0BC7085F6039007353D6 /* QualifiedName.cpp */; };
2329
		550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */ = {isa = PBXBuildFile; fileRef = 550A0BC8085F6039007353D6 /* QualifiedName.h */; settings = {ATTRIBUTES = (Private, ); }; };
2330
		550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */ = {isa = PBXBuildFile; fileRef = 550A0BC8085F6039007353D6 /* QualifiedName.h */; settings = {ATTRIBUTES = (Private, ); }; };
2330
		555B87EC1CAAF0AB00349425 /* ImageDecoderCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */; };
2331
		555B87EC1CAAF0AB00349425 /* ImageDecoderCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */; };
Lines 9992-9997 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
9992
		53ED3FDC167A88E7006762E6 /* JSInternalSettingsGenerated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInternalSettingsGenerated.cpp; sourceTree = "<group>"; };
9993
		53ED3FDC167A88E7006762E6 /* JSInternalSettingsGenerated.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSInternalSettingsGenerated.cpp; sourceTree = "<group>"; };
9993
		53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalSettingsGenerated.h; sourceTree = "<group>"; };
9994
		53ED3FDD167A88E7006762E6 /* JSInternalSettingsGenerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalSettingsGenerated.h; sourceTree = "<group>"; };
9994
		53EF766A16530A61004CBE49 /* SettingsMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsMacros.h; sourceTree = "<group>"; };
9995
		53EF766A16530A61004CBE49 /* SettingsMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsMacros.h; sourceTree = "<group>"; };
9996
		5504E4CA1D35532D00FE5088 /* BitmapPixels.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BitmapPixels.h; sourceTree = "<group>"; };
9995
		550A0BC7085F6039007353D6 /* QualifiedName.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QualifiedName.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
9997
		550A0BC7085F6039007353D6 /* QualifiedName.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QualifiedName.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
9996
		550A0BC8085F6039007353D6 /* QualifiedName.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = QualifiedName.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
9998
		550A0BC8085F6039007353D6 /* QualifiedName.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = QualifiedName.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
9997
		555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
9999
		555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
Lines 22124-22129 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
22124
				BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
22126
				BEF29EE91715DD0900C4B4C9 /* AudioTrackPrivate.h */,
22125
				A89943270B42338700D7C802 /* BitmapImage.cpp */,
22127
				A89943270B42338700D7C802 /* BitmapImage.cpp */,
22126
				A89943260B42338700D7C802 /* BitmapImage.h */,
22128
				A89943260B42338700D7C802 /* BitmapImage.h */,
22129
				5504E4CA1D35532D00FE5088 /* BitmapPixels.h */,
22127
				CDDE02E918B3DFC700CF7FF1 /* CDMSession.h */,
22130
				CDDE02E918B3DFC700CF7FF1 /* CDMSession.h */,
22128
				B27535380B053814002CE64F /* Color.cpp */,
22131
				B27535380B053814002CE64F /* Color.cpp */,
22129
				B27535390B053814002CE64F /* Color.h */,
22132
				B27535390B053814002CE64F /* Color.h */,
Lines 28370-28375 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
28370
				B22279930D00BF220071B782 /* SVGAnimateMotionElement.h in Headers */,
28373
				B22279930D00BF220071B782 /* SVGAnimateMotionElement.h in Headers */,
28371
				B22279950D00BF220071B782 /* SVGAnimateTransformElement.h in Headers */,
28374
				B22279950D00BF220071B782 /* SVGAnimateTransformElement.h in Headers */,
28372
				B22279980D00BF220071B782 /* SVGAnimationElement.h in Headers */,
28375
				B22279980D00BF220071B782 /* SVGAnimationElement.h in Headers */,
28376
				5504E4CB1D3557B200FE5088 /* BitmapPixels.h in Headers */,
28373
				439D334513A6911C00C20F4F /* SVGAnimatorFactory.h in Headers */,
28377
				439D334513A6911C00C20F4F /* SVGAnimatorFactory.h in Headers */,
28374
				08FB3F8413BC754C0099FC18 /* SVGAttributeToPropertyMap.h in Headers */,
28378
				08FB3F8413BC754C0099FC18 /* SVGAttributeToPropertyMap.h in Headers */,
28375
				B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */,
28379
				B222799C0D00BF220071B782 /* SVGCircleElement.h in Headers */,
- a/Source/WebCore/platform/graphics/BitmapPixels.h +183 lines
Line 0 a/Source/WebCore/platform/graphics/BitmapPixels.h_sec1
1
/*
2
 * Copyright (C) 2016 Apple Inc.  All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 */
25
26
#pragma once
27
28
#include "Color.h"
29
#include "IntRect.h"
30
#include "IntSize.h"
31
#include "NativeImagePtr.h"
32
33
#include <wtf/Vector.h>
34
35
namespace WebCore {
36
37
class BitmapPixels {
38
public:
39
    static std::unique_ptr<BitmapPixels> create(const IntSize& size, bool premultiplyAlpha)
40
    {
41
        return std::make_unique<BitmapPixels>(size, premultiplyAlpha);
42
    }
43
44
    static std::unique_ptr<BitmapPixels> create(const BitmapPixels& other)
45
    {
46
        return std::make_unique<BitmapPixels>(other);
47
    }
48
49
    BitmapPixels(const IntSize& size, bool premultiplyAlpha = true)
50
        : m_premultiplyAlpha(premultiplyAlpha)
51
    {
52
        ASSERT(!size.isEmpty());
53
        setSize(size);
54
    }
55
56
    BitmapPixels(const BitmapPixels& other)
57
    {
58
        if (this == &other)
59
            return;
60
        
61
        m_backingStore = other.m_backingStore;
62
        m_pixels = m_backingStore.data();
63
        m_size = other.m_size;
64
        m_rect = other.m_rect;
65
        m_premultiplyAlpha = other.m_premultiplyAlpha;
66
    }
67
68
    NativeImagePtr image() const;
69
70
    bool setSize(const IntSize& size)
71
    {
72
        if (!m_backingStore.tryReserveCapacity(size.area()))
73
            return false;
74
        
75
        m_backingStore.resize(size.area());
76
        m_pixels = m_backingStore.data();
77
        m_size = size;
78
        m_rect = IntRect(IntPoint(), m_size);
79
        clear();
80
        return true;
81
    }
82
    
83
    void setRect(const IntRect& rect)
84
    {
85
        ASSERT(!m_size.isEmpty());
86
        ASSERT(inBounds(rect));
87
        m_rect = rect;
88
    }
89
    
90
    IntSize size() const { return m_size; }
91
    IntRect rect() const { return m_rect; }
92
93
    RGBA32* at(int x, int y) const
94
    {
95
        return m_pixels + y * m_size.width() + x;
96
    }
97
98
    void clear()
99
    {
100
        memset(m_pixels, 0, m_size.area() * sizeof(RGBA32));
101
    }
102
103
    void clearRect(const IntRect& rect)
104
    {
105
        if (rect.isEmpty() || inBounds(rect))
106
            return;
107
        
108
        size_t rectWidthInBytes = rect.width() * sizeof(RGBA32);
109
        RGBA32* start = at(rect.x(), rect.y());
110
        for (int i = 0; i < rect.height(); ++i) {
111
            memset(start, 0, rectWidthInBytes);
112
            start += m_size.width();
113
        }
114
    }
115
116
    void repeatFirstRow(const IntRect& rect)
117
    {
118
        if (rect.isEmpty() || inBounds(rect))
119
            return;
120
        
121
        size_t rectWidthInBytes = rect.width() * sizeof(RGBA32);
122
        RGBA32* src = at(rect.x(), rect.y());
123
        RGBA32* dest = src + m_size.width();
124
        for (int i = 1; i < rect.height(); ++i) {
125
            memcpy(dest, src, rectWidthInBytes);
126
            dest += m_size.width();
127
        }
128
    }
129
130
    void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
131
    {
132
        setRGBA(at(x, y), r, g, b, a);
133
    }
134
135
    void setRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
136
    {
137
        if (!m_premultiplyAlpha || a >= 255)
138
            *dest = makeRGBA(r, g, b, a);
139
        else if (!a)
140
            *dest = 0;
141
        else
142
            *dest = makePremultipliedRGBA(r, g, b, a);
143
    }
144
145
    void overRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
146
    {
147
        if (!a)
148
            return;
149
        
150
        if (a >= 255 || !alphaChannel(*dest)) {
151
            setRGBA(dest, r, g, b, a);
152
            return;
153
        }
154
        
155
        if (!m_premultiplyAlpha)
156
            *dest = makePremultipliedRGBA(redChannel(*dest), greenChannel(*dest), blueChannel(*dest), alphaChannel(*dest));
157
        
158
        RGBA32 src = makeRGBA(r, g, b, a);
159
        *dest = Color(*dest).blend(src).rgb();
160
        
161
        if (!m_premultiplyAlpha)
162
            *dest = makeUnPremultipliedRGBA(redChannel(*dest), greenChannel(*dest), blueChannel(*dest), alphaChannel(*dest));
163
    }
164
165
    bool inBounds(const IntPoint& point) const
166
    {
167
        return IntRect(IntPoint(), m_size).contains(point);
168
    }
169
170
    bool inBounds(const IntRect& rect) const
171
    {
172
        return IntRect(IntPoint(), m_size).contains(rect);
173
    }
174
175
private:
176
    Vector<RGBA32> m_backingStore;
177
    RGBA32* m_pixels { nullptr };
178
    IntSize m_size;
179
    IntRect m_rect; // This will always just be the entire buffer except for GIF and PNG frames
180
    bool m_premultiplyAlpha { true };
181
};
182
183
}
- a/Source/WebCore/platform/graphics/Color.cpp +44 lines
Lines 49-54 const RGBA32 Color::transparent; a/Source/WebCore/platform/graphics/Color.cpp_sec1
49
static const RGBA32 lightenedBlack = 0xFF545454;
49
static const RGBA32 lightenedBlack = 0xFF545454;
50
static const RGBA32 darkenedWhite = 0xFFABABAB;
50
static const RGBA32 darkenedWhite = 0xFFABABAB;
51
51
52
static inline unsigned multiply255(unsigned c)
53
{
54
    // c * 255
55
    //   = c * (256 - 1)
56
    //   = c * 256 - c
57
    return (c << 8) - c;
58
}
59
60
static inline unsigned divide255(unsigned c)
61
{
62
    // c / 255
63
    //   = c / 256 * (1 + 1 / 255)
64
    //   = (c + c / 255) / 256
65
    //   = (c + (c + c / 255) / 256) / 256
66
    //   = (c + c / 256 + c / (255 x 256)) / 256
67
    //  ~= (c + c / 256 + 1) / 256
68
    return (c + (c >> 8) + 1) >> 8;
69
}
70
    
71
static inline unsigned divideCeil(unsigned c, unsigned d)
72
{
73
    return (c + d - 1) / d;
74
}
75
    
76
static inline unsigned premultipliedChannel(unsigned c, unsigned a)
77
{
78
    return divide255(c * a);
79
}
80
81
static inline unsigned unpremultipliedChannel(unsigned c, unsigned a)
82
{
83
    return divideCeil(multiply255(c), a);
84
}
85
    
52
RGBA32 makeRGB(int r, int g, int b)
86
RGBA32 makeRGB(int r, int g, int b)
53
{
87
{
54
    return 0xFF000000 | std::max(0, std::min(r, 255)) << 16 | std::max(0, std::min(g, 255)) << 8 | std::max(0, std::min(b, 255));
88
    return 0xFF000000 | std::max(0, std::min(r, 255)) << 16 | std::max(0, std::min(g, 255)) << 8 | std::max(0, std::min(b, 255));
Lines 59-64 RGBA32 makeRGBA(int r, int g, int b, int a) a/Source/WebCore/platform/graphics/Color.cpp_sec2
59
    return std::max(0, std::min(a, 255)) << 24 | std::max(0, std::min(r, 255)) << 16 | std::max(0, std::min(g, 255)) << 8 | std::max(0, std::min(b, 255));
93
    return std::max(0, std::min(a, 255)) << 24 | std::max(0, std::min(r, 255)) << 16 | std::max(0, std::min(g, 255)) << 8 | std::max(0, std::min(b, 255));
60
}
94
}
61
95
96
RGBA32 makePremultipliedRGBA(int r, int g, int b, int a)
97
{
98
    return makeRGBA(premultipliedChannel(r, a), premultipliedChannel(g, a), premultipliedChannel(b, a), a);
99
}
100
    
101
RGBA32 makeUnPremultipliedRGBA(int r, int g, int b, int a)
102
{
103
    return makeRGBA(unpremultipliedChannel(r, a), unpremultipliedChannel(g, a), unpremultipliedChannel(b, a), a);
104
}
105
    
62
static int colorFloatToRGBAByte(float f)
106
static int colorFloatToRGBAByte(float f)
63
{
107
{
64
    // We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
108
    // We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
- a/Source/WebCore/platform/graphics/Color.h +2 lines
Lines 54-59 typedef unsigned RGBA32; // Deprecated: Type for an RGBA quadruplet. Use RGBA cl a/Source/WebCore/platform/graphics/Color.h_sec1
54
54
55
WEBCORE_EXPORT RGBA32 makeRGB(int r, int g, int b);
55
WEBCORE_EXPORT RGBA32 makeRGB(int r, int g, int b);
56
WEBCORE_EXPORT RGBA32 makeRGBA(int r, int g, int b, int a);
56
WEBCORE_EXPORT RGBA32 makeRGBA(int r, int g, int b, int a);
57
WEBCORE_EXPORT RGBA32 makePremultipliedRGBA(int r, int g, int b, int a);
58
WEBCORE_EXPORT RGBA32 makeUnPremultipliedRGBA(int r, int g, int b, int a);
57
59
58
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, float overrideAlpha);
60
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, float overrideAlpha);
59
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, Optional<float> overrideAlpha);
61
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, Optional<float> overrideAlpha);
- a/Source/WebCore/platform/graphics/ImageFrameData.cpp +18 lines
Lines 75-80 ImageFrameData::~ImageFrameData() a/Source/WebCore/platform/graphics/ImageFrameData.cpp_sec1
75
{
75
{
76
    clearSubImages();
76
    clearSubImages();
77
}
77
}
78
    
79
ImageFrameData& ImageFrameData::operator=(const ImageFrameData& other)
80
{
81
    if (this == &other)
82
        return *this;
83
84
    m_status = other.m_status;
85
    m_size = other.m_size;
86
    m_image = other.m_image;
87
    
88
    m_pixels = other.pixels() ? BitmapPixels::create(*other.pixels()) : nullptr;
89
    
90
    m_orientation = other.m_orientation;
91
    m_subsamplingLevel = other.m_subsamplingLevel;
92
    m_duration = other.m_duration;
93
    m_hasAlpha = other.m_hasAlpha;
94
    return *this;
95
}
78
96
79
void ImageFrameData::clearSubImages()
97
void ImageFrameData::clearSubImages()
80
{
98
{
- a/Source/WebCore/platform/graphics/ImageFrameData.h -3 / +16 lines
Lines 25-30 a/Source/WebCore/platform/graphics/ImageFrameData.h_sec1
25
25
26
#pragma once
26
#pragma once
27
27
28
#include "BitmapPixels.h"
28
#include "ImageOrientation.h"
29
#include "ImageOrientation.h"
29
#include "IntSize.h"
30
#include "IntSize.h"
30
#include "NativeImagePtr.h"
31
#include "NativeImagePtr.h"
Lines 44-49 enum : SubsamplingLevel { a/Source/WebCore/platform/graphics/ImageFrameData.h_sec2
44
};
45
};
45
46
46
class ImageFrameData {
47
class ImageFrameData {
48
    friend class ImageDecoder;
47
public:
49
public:
48
    enum class Caching { Empty, Metadata, Image, MetadataAndImage };
50
    enum class Caching { Empty, Metadata, Image, MetadataAndImage };
49
    enum class DecodingStatus { Empty, Partial, Complete };
51
    enum class DecodingStatus { Empty, Partial, Complete };
Lines 51-58 public: a/Source/WebCore/platform/graphics/ImageFrameData.h_sec3
51
    ImageFrameData();
53
    ImageFrameData();
52
    ImageFrameData(NativeImagePtr&&);
54
    ImageFrameData(NativeImagePtr&&);
53
    ImageFrameData(ImageDecoder&, size_t index, SubsamplingLevel = DefaultSubsamplingLevel, Caching = Caching::MetadataAndImage);
55
    ImageFrameData(ImageDecoder&, size_t index, SubsamplingLevel = DefaultSubsamplingLevel, Caching = Caching::MetadataAndImage);
54
    
56
    ImageFrameData(const ImageFrameData& other) { operator=(other); }
57
55
    ~ImageFrameData();
58
    ~ImageFrameData();
59
60
    ImageFrameData& operator=(const ImageFrameData& other);
56
    
61
    
57
    unsigned clear(Caching);
62
    unsigned clear(Caching);
58
    Color singlePixelSolidColor() const;
63
    Color singlePixelSolidColor() const;
Lines 60-68 public: a/Source/WebCore/platform/graphics/ImageFrameData.h_sec4
60
    
65
    
61
    DecodingStatus status() const { return m_status; }
66
    DecodingStatus status() const { return m_status; }
62
    bool isComplete() const { return m_status == DecodingStatus::Complete; }
67
    bool isComplete() const { return m_status == DecodingStatus::Complete; }
63
    IntSize size() const { return m_size; }
68
    IntSize size() const { return hasPixels() ? pixels()->size() : m_size; }
64
    unsigned frameBytes() const { return hasImage() ? m_size.area() * 4 : 0; }
69
    unsigned frameBytes() const { return hasImage() ? m_size.area() * sizeof(RGBA32) : 0; }
65
    NativeImagePtr image() const { return m_image; }
70
    NativeImagePtr image() const { return m_image; }
71
    BitmapPixels* pixels() const { return m_pixels ? m_pixels.get() : nullptr; }
66
    
72
    
67
    ImageOrientation orientation() const { return m_orientation; }
73
    ImageOrientation orientation() const { return m_orientation; }
68
    SubsamplingLevel subsamplingLevel() const { return m_subsamplingLevel; }
74
    SubsamplingLevel subsamplingLevel() const { return m_subsamplingLevel; }
Lines 71-83 public: a/Source/WebCore/platform/graphics/ImageFrameData.h_sec5
71
    bool hasAlpha() const { return m_hasAlpha; }
77
    bool hasAlpha() const { return m_hasAlpha; }
72
    bool hasImage() const { return m_image; }
78
    bool hasImage() const { return m_image; }
73
    bool hasMetadata() const { return !m_size.isEmpty(); }
79
    bool hasMetadata() const { return !m_size.isEmpty(); }
80
    bool hasPixels() const { return pixels(); }
74
    
81
    
75
private:
82
private:
76
    void clearSubImages();
83
    void clearSubImages();
84
85
    void setStatus(DecodingStatus status) { m_status = status; }
86
    void setOrientation(ImageOrientation orientation) { m_orientation = orientation; };
87
    void setDuration(unsigned duration) { m_duration = duration; }
88
    void setHasAlpha(bool hasAlpha) { m_hasAlpha = hasAlpha; }
77
    
89
    
78
    DecodingStatus m_status { DecodingStatus::Empty };
90
    DecodingStatus m_status { DecodingStatus::Empty };
79
    IntSize m_size;
91
    IntSize m_size;
80
    NativeImagePtr m_image;
92
    NativeImagePtr m_image;
93
    std::unique_ptr<BitmapPixels> m_pixels;
81
    
94
    
82
    ImageOrientation m_orientation { DefaultImageOrientation };
95
    ImageOrientation m_orientation { DefaultImageOrientation };
83
    SubsamplingLevel m_subsamplingLevel { 0 };
96
    SubsamplingLevel m_subsamplingLevel { 0 };
- a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp -27 / +16 lines
Lines 142-148 ImageFrame& ImageFrame::operator=(const ImageFrame& other) a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec1
142
        return *this;
142
        return *this;
143
143
144
    copyBitmapData(other);
144
    copyBitmapData(other);
145
    setOriginalFrameRect(other.originalFrameRect());
145
    setHasAlpha(other.m_hasAlpha);
146
    setStatus(other.status());
146
    setStatus(other.status());
147
    setDuration(other.duration());
147
    setDuration(other.duration());
148
    setDisposalMethod(other.disposalMethod());
148
    setDisposalMethod(other.disposalMethod());
Lines 152-159 ImageFrame& ImageFrame::operator=(const ImageFrame& other) a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec2
152
152
153
void ImageFrame::clearPixelData()
153
void ImageFrame::clearPixelData()
154
{
154
{
155
    m_backingStore.clear();
155
    m_pixels = nullptr;
156
    m_bytes = 0;
157
    m_status = FrameEmpty;
156
    m_status = FrameEmpty;
158
    // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
157
    // NOTE: Do not reset other members here; clearFrameBufferCache() calls this
159
    // to free the bitmap data, but other functions like initFrameBuffer() and
158
    // to free the bitmap data, but other functions like initFrameBuffer() and
Lines 163-186 void ImageFrame::clearPixelData() a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec3
163
162
164
void ImageFrame::zeroFillPixelData()
163
void ImageFrame::zeroFillPixelData()
165
{
164
{
166
    memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData));
165
    m_pixels->clear();
167
    m_hasAlpha = true;
166
    m_hasAlpha = true;
168
}
167
}
169
168
170
void ImageFrame::zeroFillFrameRect(const IntRect& rect)
169
void ImageFrame::zeroFillFrameRect(const IntRect& rect)
171
{
170
{
172
    ASSERT(IntRect(IntPoint(), m_size).contains(rect));
173
174
    if (rect.isEmpty())
171
    if (rect.isEmpty())
175
        return;
172
        return;
176
173
177
    size_t rectWidthInBytes = rect.width() * sizeof(PixelData);
174
    m_pixels->clearRect(rect);
178
    PixelData* start = m_bytes + (rect.y() * width()) + rect.x();
179
    for (int i = 0; i < rect.height(); ++i) {
180
        memset(start, 0, rectWidthInBytes);
181
        start += width();
182
    }
183
184
    setHasAlpha(true);
175
    setHasAlpha(true);
185
}
176
}
186
177
Lines 189-213 bool ImageFrame::copyBitmapData(const ImageFrame& other) a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec4
189
    if (this == &other)
180
    if (this == &other)
190
        return true;
181
        return true;
191
182
192
    m_backingStore = other.m_backingStore;
183
    if (other.m_pixels)
193
    m_bytes = m_backingStore.data();
184
        m_pixels = BitmapPixels::create(*other.m_pixels.get());
194
    m_size = other.m_size;
185
    else
195
    setHasAlpha(other.m_hasAlpha);
186
        m_pixels = nullptr;
196
    return true;
187
    return true;
197
}
188
}
198
189
199
bool ImageFrame::setSize(int newWidth, int newHeight)
190
bool ImageFrame::setSize(int newWidth, int newHeight)
200
{
191
{
201
    ASSERT(!width() && !height());
192
    ASSERT(!m_pixels);
202
    size_t backingStoreSize = newWidth * newHeight;
193
    m_pixels = BitmapPixels::create(IntSize(newWidth, newHeight), m_premultiplyAlpha);
203
    if (!m_backingStore.tryReserveCapacity(backingStoreSize))
194
    return m_pixels != nullptr;
204
        return false;
195
}
205
    m_backingStore.resize(backingStoreSize);
206
    m_bytes = m_backingStore.data();
207
    m_size = IntSize(newWidth, newHeight);
208
196
209
    zeroFillPixelData();
197
void ImageFrame::copyRowNTimes(int startX, int endX, int startY, int endY)
210
    return true;
198
{
199
    m_pixels->repeatFirstRow(IntRect(startX, startY, endX -startX , endY - startY));
211
}
200
}
212
201
213
bool ImageFrame::hasAlpha() const
202
bool ImageFrame::hasAlpha() const
Lines 291-297 unsigned ImageDecoder::frameBytesAtIndex(size_t index) const a/Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec5
291
    if (m_frameBufferCache.size() <= index)
280
    if (m_frameBufferCache.size() <= index)
292
        return 0;
281
        return 0;
293
    // FIXME: Use the dimension of the requested frame.
282
    // FIXME: Use the dimension of the requested frame.
294
    return m_size.area() * sizeof(ImageFrame::PixelData);
283
    return m_size.area() * sizeof(RGBA32);
295
}
284
}
296
285
297
float ImageDecoder::frameDurationAtIndex(size_t index)
286
float ImageDecoder::frameDurationAtIndex(size_t index)
- a/Source/WebCore/platform/image-decoders/ImageDecoder.h -99 / +16 lines
Lines 28-33 a/Source/WebCore/platform/image-decoders/ImageDecoder.h_sec1
28
28
29
#pragma once
29
#pragma once
30
30
31
#include "BitmapPixels.h"
31
#include "IntRect.h"
32
#include "IntRect.h"
32
#include "ImageSource.h"
33
#include "ImageSource.h"
33
#include "PlatformScreen.h"
34
#include "PlatformScreen.h"
Lines 57-63 using ColorProfile = Vector<char>; a/Source/WebCore/platform/image-decoders/ImageDecoder.h_sec2
57
            DisposeOverwritePrevious  // Clear frame to previous framebuffer
58
            DisposeOverwritePrevious  // Clear frame to previous framebuffer
58
                                      // contents
59
                                      // contents
59
        };
60
        };
60
        typedef unsigned PixelData;
61
61
62
        ImageFrame();
62
        ImageFrame();
63
63
Lines 80-109 using ColorProfile = Vector<char>; a/Source/WebCore/platform/image-decoders/ImageDecoder.h_sec3
80
        // Copies the pixel data at [(startX, startY), (endX, startY)) to the
80
        // Copies the pixel data at [(startX, startY), (endX, startY)) to the
81
        // same X-coordinates on each subsequent row up to but not including
81
        // same X-coordinates on each subsequent row up to but not including
82
        // endY.
82
        // endY.
83
        void copyRowNTimes(int startX, int endX, int startY, int endY)
83
        void copyRowNTimes(int startX, int endX, int startY, int endY);
84
        {
85
            ASSERT(startX < width());
86
            ASSERT(endX <= width());
87
            ASSERT(startY < height());
88
            ASSERT(endY <= height());
89
            const int rowBytes = (endX - startX) * sizeof(PixelData);
90
            const PixelData* const startAddr = getAddr(startX, startY);
91
            for (int destY = startY + 1; destY < endY; ++destY)
92
                memcpy(getAddr(startX, destY), startAddr, rowBytes);
93
        }
94
84
95
        // Allocates space for the pixel data.  Must be called before any pixels
85
        // Allocates space for the pixel data.  Must be called before any pixels
96
        // are written.  Must only be called once.  Returns whether allocation
86
        // are written.  Must only be called once.  Returns whether allocation
97
        // succeeded.
87
        // succeeded.
98
        bool setSize(int newWidth, int newHeight);
88
        bool setSize(int newWidth, int newHeight);
89
        
90
        IntSize size() const { return m_pixels->size(); }
99
91
100
        // Returns a caller-owned pointer to the underlying native image data.
92
        // Returns a caller-owned pointer to the underlying native image data.
101
        // (Actual use: This pointer will be owned by BitmapImage and freed in
93
        // (Actual use: This pointer will be owned by BitmapImage and freed in
102
        // FrameData::clear()).
94
        // FrameData::clear()).
103
        NativeImagePtr asNewNativeImage() const;
95
        NativeImagePtr asNewNativeImage() const { return m_pixels->image(); }
96
97
        inline BitmapPixels* pixels() const { return m_pixels ? m_pixels.get() : nullptr; }
98
        inline bool hasPixels() const { return pixels(); }
104
99
105
        bool hasAlpha() const;
100
        bool hasAlpha() const;
106
        const IntRect& originalFrameRect() const { return m_originalFrameRect; }
107
        FrameStatus status() const { return m_status; }
101
        FrameStatus status() const { return m_status; }
108
        unsigned duration() const { return m_duration; }
102
        unsigned duration() const { return m_duration; }
109
        FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
103
        FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
Lines 111-117 using ColorProfile = Vector<char>; a/Source/WebCore/platform/image-decoders/ImageDecoder.h_sec4
111
105
112
        void setHasAlpha(bool alpha);
106
        void setHasAlpha(bool alpha);
113
        void setColorProfile(const ColorProfile&);
107
        void setColorProfile(const ColorProfile&);
114
        void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
115
        void setStatus(FrameStatus status);
108
        void setStatus(FrameStatus status);
116
        void setDuration(unsigned duration) { m_duration = duration; }
109
        void setDuration(unsigned duration) { m_duration = duration; }
117
        void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
110
        void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
Lines 119-226 using ColorProfile = Vector<char>; a/Source/WebCore/platform/image-decoders/ImageDecoder.h_sec5
119
112
120
        inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
113
        inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
121
        {
114
        {
122
            setRGBA(getAddr(x, y), r, g, b, a);
115
            m_pixels->setRGBA(x, y, r, g, b, a);
123
        }
116
        }
124
117
125
        inline PixelData* getAddr(int x, int y)
118
        inline RGBA32* getAddr(int x, int y)
126
        {
119
        {
127
            return m_bytes + (y * width()) + x;
120
            return m_pixels->at(x, y);
128
        }
121
        }
129
122
130
        inline bool hasPixelData() const
123
        inline void setRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
131
        {
124
        {
132
            return m_bytes;
125
            m_pixels->setRGBA(dest, r, g, b, a);
133
        }
134
135
        // Use fix point multiplier instead of integer division or floating point math.
136
        // This multipler produces exactly the same result for all values in range 0 - 255.
137
        static const unsigned fixPointShift = 24;
138
        static const unsigned fixPointMult = static_cast<unsigned>(1.0 / 255.0 * (1 << fixPointShift)) + 1;
139
        // Multiplies unsigned value by fixpoint value and converts back to unsigned.
140
        static unsigned fixPointUnsignedMultiply(unsigned fixed, unsigned v)
141
        {
142
            return  (fixed * v) >> fixPointShift;
143
        }
144
145
        inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
146
        {
147
            if (m_premultiplyAlpha && a < 255) {
148
                if (!a) {
149
                    *dest = 0;
150
                    return;
151
                }
152
153
                unsigned alphaMult = a * fixPointMult;
154
                r = fixPointUnsignedMultiply(r, alphaMult);
155
                g = fixPointUnsignedMultiply(g, alphaMult);
156
                b = fixPointUnsignedMultiply(b, alphaMult);
157
            }
158
            *dest = (a << 24 | r << 16 | g << 8 | b);
159
        }
126
        }
160
127
161
#if ENABLE(APNG)
128
#if ENABLE(APNG)
162
        static inline unsigned divide255(unsigned a)
129
        inline void overRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
163
        {
130
        {
164
            return (a + (a >> 8) + 1) >> 8;
131
            m_pixels->overRGBA(dest, r, g, b, a);
165
        }
166
167
        inline void overRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
168
        {
169
            if (!a)
170
                return;
171
172
            if (a < 255) {
173
                unsigned aDest = ((*dest) >> 24) & 255;
174
                if (aDest) {
175
                    unsigned rDest = ((*dest) >> 16) & 255;
176
                    unsigned gDest = ((*dest) >> 8) & 255;
177
                    unsigned bDest = (*dest) & 255;
178
                    unsigned aAux = 255 - a;
179
                    if (!m_premultiplyAlpha) {
180
                        rDest = divide255(rDest * aDest);
181
                        gDest = divide255(gDest * aDest);
182
                        bDest = divide255(bDest * aDest);
183
                    }
184
                    r = divide255(r * a + rDest * aAux);
185
                    g = divide255(g * a + gDest * aAux);
186
                    b = divide255(b * a + bDest * aAux);
187
                    a += divide255(aDest * aAux);
188
                    if (!m_premultiplyAlpha) {
189
                        r = (r * 255 + a - 1) / a;
190
                        g = (g * 255 + a - 1) / a;
191
                        b = (b * 255 + a - 1) / a;
192
                    }
193
                } else if (m_premultiplyAlpha) {
194
                    r = divide255(r * a);
195
                    g = divide255(g * a);
196
                    b = divide255(b * a);
197
                }
198
            }
199
            *dest = (a << 24 | r << 16 | g << 8 | b);
200
        }
132
        }
201
#endif
133
#endif
202
134
203
    private:
135
    private:
204
        int width() const
136
        std::unique_ptr<BitmapPixels> m_pixels;
205
        {
206
            return m_size.width();
207
        }
208
137
209
        int height() const
210
        {
211
            return m_size.height();
212
        }
213
214
        Vector<PixelData> m_backingStore;
215
        PixelData* m_bytes; // The memory is backed by m_backingStore.
216
        IntSize m_size;
217
        // FIXME: Do we need m_colorProfile anymore?
138
        // FIXME: Do we need m_colorProfile anymore?
218
        ColorProfile m_colorProfile;
139
        ColorProfile m_colorProfile;
219
        bool m_hasAlpha;
140
        bool m_hasAlpha;
220
        IntRect m_originalFrameRect; // This will always just be the entire
221
                                     // buffer except for GIF frames whose
222
                                     // original rect was smaller than the
223
                                     // overall image size.
224
        FrameStatus m_status;
141
        FrameStatus m_status;
225
        unsigned m_duration;
142
        unsigned m_duration;
226
        FrameDisposalMethod m_disposalMethod;
143
        FrameDisposalMethod m_disposalMethod;
- a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp -3 lines
Lines 86-94 bool BMPImageReader::decodeBMP(bool onlySize) a/Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp_sec1
86
        // these 0s could actually show through.
86
        // these 0s could actually show through.
87
        m_buffer->setHasAlpha(false);
87
        m_buffer->setHasAlpha(false);
88
88
89
        // For BMPs, the frame always fills the entire image.
90
        m_buffer->setOriginalFrameRect(IntRect(IntPoint(), m_parent->size()));
91
92
        if (!m_isTopDown)
89
        if (!m_isTopDown)
93
            m_coord.setY(m_parent->size().height() - 1);
90
            m_coord.setY(m_parent->size().height() - 1);
94
    }
91
    }
- a/Source/WebCore/platform/image-decoders/cairo/BitmapPixelsCairo.cpp -5 / +5 lines
Lines 1-5 a/Source/WebCore/platform/image-decoders/cairo/BitmapPixelsCairo.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2006 Apple Inc.  All rights reserved.
2
 * Copyright (C) 2016 Apple Inc.  All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
5
 * modification, are permitted provided that the following conditions
Lines 24-40 a/Source/WebCore/platform/image-decoders/cairo/BitmapPixelsCairo.cpp_sec2
24
 */
24
 */
25
25
26
#include "config.h"
26
#include "config.h"
27
#include "ImageDecoder.h"
27
#include "BitmapPixels.h"
28
28
29
#include <cairo.h>
29
#include <cairo.h>
30
30
31
namespace WebCore {
31
namespace WebCore {
32
32
33
NativeImagePtr ImageFrame::asNewNativeImage() const
33
NativeImagePtr BitmapPixels::image() const
34
{
34
{
35
    return adoptRef(cairo_image_surface_create_for_data(
35
    return adoptRef(cairo_image_surface_create_for_data(
36
        reinterpret_cast<unsigned char*>(const_cast<PixelData*>(m_bytes)),
36
        reinterpret_cast<unsigned char*>(const_cast<RGBA32*>(m_pixels)),
37
        CAIRO_FORMAT_ARGB32, width(), height(), width() * sizeof(PixelData)));
37
        CAIRO_FORMAT_ARGB32, size().width(), size().height(), size().width() * sizeof(RGBA32)));
38
}
38
}
39
39
40
} // namespace WebCore
40
} // namespace WebCore
- a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp -10 / +11 lines
Lines 213-222 bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, const Vector<unsigned a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec1
213
213
214
    // Initialize the frame if necessary.
214
    // Initialize the frame if necessary.
215
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
215
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
216
    if (((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) || !buffer.hasPixelData())
216
    if (((buffer.status() == ImageFrame::FrameEmpty) && !initFrameBuffer(frameIndex)) || !buffer.hasPixels())
217
        return false;
217
        return false;
218
218
219
    ImageFrame::PixelData* currentAddress = buffer.getAddr(xBegin, yBegin);
219
    RGBA32* currentAddress = buffer.getAddr(xBegin, yBegin);
220
    // Write one row's worth of data into the frame.  
220
    // Write one row's worth of data into the frame.  
221
    for (int x = xBegin; x < xEnd; ++x) {
221
    for (int x = xBegin; x < xEnd; ++x) {
222
        const unsigned char sourceValue = rowBuffer[(m_scaled ? m_scaledColumns[x] : x) - frameContext->xOffset];
222
        const unsigned char sourceValue = rowBuffer[(m_scaled ? m_scaledColumns[x] : x) - frameContext->xOffset];
Lines 260-266 bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec2
260
    if (!m_currentBufferSawAlpha) {
260
    if (!m_currentBufferSawAlpha) {
261
        // The whole frame was non-transparent, so it's possible that the entire
261
        // The whole frame was non-transparent, so it's possible that the entire
262
        // resulting buffer was non-transparent, and we can setHasAlpha(false).
262
        // resulting buffer was non-transparent, and we can setHasAlpha(false).
263
        if (buffer.originalFrameRect().contains(IntRect(IntPoint(), scaledSize())))
263
        if (buffer.pixels()->rect().contains(IntRect(IntPoint(), scaledSize())))
264
            buffer.setHasAlpha(false);
264
            buffer.setHasAlpha(false);
265
        else if (frameIndex) {
265
        else if (frameIndex) {
266
            // Tricky case.  This frame does not have alpha only if everywhere
266
            // Tricky case.  This frame does not have alpha only if everywhere
Lines 283-289 bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec3
283
            // The only remaining case is a DisposeOverwriteBgcolor frame.  If
283
            // The only remaining case is a DisposeOverwriteBgcolor frame.  If
284
            // it had no alpha, and its rect is contained in the current frame's
284
            // it had no alpha, and its rect is contained in the current frame's
285
            // rect, we know the current frame has no alpha.
285
            // rect, we know the current frame has no alpha.
286
            if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
286
            if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.pixels()->rect().contains(prevBuffer->pixels()->rect()))
287
                buffer.setHasAlpha(false);
287
                buffer.setHasAlpha(false);
288
        }
288
        }
289
    }
289
    }
Lines 353-363 bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec4
353
        frameRect.setHeight(size().height() - frameContext->yOffset);
353
        frameRect.setHeight(size().height() - frameContext->yOffset);
354
354
355
    ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
355
    ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
356
    int left = upperBoundScaledX(frameRect.x());
357
    int right = lowerBoundScaledX(frameRect.maxX(), left);
358
    int top = upperBoundScaledY(frameRect.y());
359
    int bottom = lowerBoundScaledY(frameRect.maxY(), top);
360
    buffer->setOriginalFrameRect(IntRect(left, top, right - left, bottom - top));
361
356
362
    if (!frameIndex) {
357
    if (!frameIndex) {
363
        // This is the first frame, so we're not relying on any previous data.
358
        // This is the first frame, so we're not relying on any previous data.
Lines 387-393 bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec5
387
        } else {
382
        } else {
388
            // We want to clear the previous frame to transparent, without
383
            // We want to clear the previous frame to transparent, without
389
            // affecting pixels in the image outside of the frame.
384
            // affecting pixels in the image outside of the frame.
390
            const IntRect& prevRect = prevBuffer->originalFrameRect();
385
            const IntRect& prevRect = prevBuffer->pixels()->rect();
391
            const IntSize& bufferSize = scaledSize();
386
            const IntSize& bufferSize = scaledSize();
392
            if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
387
            if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
393
                // Clearing the first frame, or a frame the size of the whole
388
                // Clearing the first frame, or a frame the size of the whole
Lines 402-407 bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) a/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec6
402
            }
397
            }
403
        }
398
        }
404
    }
399
    }
400
    
401
    int left = upperBoundScaledX(frameRect.x());
402
    int right = lowerBoundScaledX(frameRect.maxX(), left);
403
    int top = upperBoundScaledY(frameRect.y());
404
    int bottom = lowerBoundScaledY(frameRect.maxY(), top);
405
    buffer->pixels()->setRect(IntRect(left, top, right - left, bottom - top));
405
406
406
    // Update our status to be partially complete.
407
    // Update our status to be partially complete.
407
    buffer->setStatus(ImageFrame::FramePartial);
408
    buffer->setStatus(ImageFrame::FramePartial);
- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp -5 / +2 lines
Lines 588-594 bool JPEGImageDecoder::setFailed() a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec1
588
}
588
}
589
589
590
template <J_COLOR_SPACE colorSpace>
590
template <J_COLOR_SPACE colorSpace>
591
void setPixel(ImageFrame& buffer, ImageFrame::PixelData* currentAddress, JSAMPARRAY samples, int column)
591
void setPixel(ImageFrame& buffer, RGBA32* currentAddress, JSAMPARRAY samples, int column)
592
{
592
{
593
    JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4);
593
    JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4);
594
594
Lines 631-637 bool JPEGImageDecoder::outputScanlines(ImageFrame& buffer) a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec2
631
        if (destY < 0)
631
        if (destY < 0)
632
            continue;
632
            continue;
633
633
634
        ImageFrame::PixelData* currentAddress = buffer.getAddr(0, destY);
634
        RGBA32* currentAddress = buffer.getAddr(0, destY);
635
        for (int x = 0; x < width; ++x) {
635
        for (int x = 0; x < width; ++x) {
636
            setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
636
            setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
637
            ++currentAddress;
637
            ++currentAddress;
Lines 661-669 bool JPEGImageDecoder::outputScanlines() a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec3
661
        // loading. The completed image will be marked fully opaque in jpegComplete().
661
        // loading. The completed image will be marked fully opaque in jpegComplete().
662
        buffer.setHasAlpha(true);
662
        buffer.setHasAlpha(true);
663
        buffer.setColorProfile(m_colorProfile);
663
        buffer.setColorProfile(m_colorProfile);
664
665
        // For JPEGs, the frame always fills the entire image.
666
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
667
    }
664
    }
668
665
669
    jpeg_decompress_struct* info = m_reader->info();
666
    jpeg_decompress_struct* info = m_reader->info();
- a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp -18 / +16 lines
Lines 452-470 void PNGImageDecoder::headerAvailable() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec1
452
    }
452
    }
453
}
453
}
454
454
455
static inline void setPixelRGB(ImageFrame::PixelData* dest, png_bytep pixel)
455
static inline void setPixelRGB(RGBA32* dest, png_bytep pixel)
456
{
456
{
457
    *dest = 0xFF000000U | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
457
    *dest = 0xFF000000U | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
458
}
458
}
459
459
460
static inline void setPixelRGBA(ImageFrame::PixelData* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
460
static inline void setPixelRGBA(RGBA32* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
461
{
461
{
462
    unsigned char a = pixel[3];
462
    unsigned char a = pixel[3];
463
    *dest = a << 24 | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
463
    *dest = a << 24 | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
464
    nonTrivialAlphaMask |= (255 - a);
464
    nonTrivialAlphaMask |= (255 - a);
465
}
465
}
466
466
467
static inline void setPixelPremultipliedRGBA(ImageFrame::PixelData* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
467
static inline void setPixelPremultipliedRGBA(RGBA32* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
468
{
468
{
469
    unsigned char a = pixel[3];
469
    unsigned char a = pixel[3];
470
    unsigned char r = fastDivideBy255(pixel[0] * a);
470
    unsigned char r = fastDivideBy255(pixel[0] * a);
Lines 511-520 void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec2
511
#if ENABLE(APNG)
511
#if ENABLE(APNG)
512
        if (m_currentFrame)
512
        if (m_currentFrame)
513
            initFrameBuffer(m_currentFrame);
513
            initFrameBuffer(m_currentFrame);
514
        else
515
#endif
514
#endif
516
        // For PNGs, the frame always fills the entire image.
517
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
518
    }
515
    }
519
516
520
    /* libpng comments (here to explain what follows).
517
    /* libpng comments (here to explain what follows).
Lines 573-579 void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec3
573
    }
570
    }
574
571
575
    // Write the decoded row pixels to the frame buffer.
572
    // Write the decoded row pixels to the frame buffer.
576
    ImageFrame::PixelData* address = buffer.getAddr(0, y);
573
    RGBA32* address = buffer.getAddr(0, y);
577
    int width = scaledSize().width();
574
    int width = scaledSize().width();
578
    unsigned char nonTrivialAlphaMask = 0;
575
    unsigned char nonTrivialAlphaMask = 0;
579
576
Lines 834-844 void PNGImageDecoder::initFrameBuffer(size_t frameIndex) a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec4
834
        frameRect.setHeight(size().height() - m_yOffset);
831
        frameRect.setHeight(size().height() - m_yOffset);
835
832
836
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
833
    ImageFrame& buffer = m_frameBufferCache[frameIndex];
837
    int left = upperBoundScaledX(frameRect.x());
838
    int right = lowerBoundScaledX(frameRect.maxX(), left);
839
    int top = upperBoundScaledY(frameRect.y());
840
    int bottom = lowerBoundScaledY(frameRect.maxY(), top);
841
    buffer.setOriginalFrameRect(IntRect(left, top, right - left, bottom - top));
842
834
843
    // The starting state for this frame depends on the previous frame's
835
    // The starting state for this frame depends on the previous frame's
844
    // disposal method.
836
    // disposal method.
Lines 862-868 void PNGImageDecoder::initFrameBuffer(size_t frameIndex) a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec5
862
    } else {
854
    } else {
863
        // We want to clear the previous frame to transparent, without
855
        // We want to clear the previous frame to transparent, without
864
        // affecting pixels in the image outside of the frame.
856
        // affecting pixels in the image outside of the frame.
865
        const IntRect& prevRect = prevBuffer->originalFrameRect();
857
        const IntRect& prevRect = prevBuffer->pixels()->rect();
866
        if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
858
        if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
867
            // Clearing the first frame, or a frame the size of the whole
859
            // Clearing the first frame, or a frame the size of the whole
868
            // image, results in a completely empty image.
860
            // image, results in a completely empty image.
Lines 873-878 void PNGImageDecoder::initFrameBuffer(size_t frameIndex) a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec6
873
            buffer.zeroFillFrameRect(prevRect);
865
            buffer.zeroFillFrameRect(prevRect);
874
        }
866
        }
875
    }
867
    }
868
    
869
    int left = upperBoundScaledX(frameRect.x());
870
    int right = lowerBoundScaledX(frameRect.maxX(), left);
871
    int top = upperBoundScaledY(frameRect.y());
872
    int bottom = lowerBoundScaledY(frameRect.maxY(), top);
873
    buffer.pixels()->setRect(IntRect(left, top, right - left, bottom - top));
876
}
874
}
877
875
878
void PNGImageDecoder::frameComplete()
876
void PNGImageDecoder::frameComplete()
Lines 886-892 void PNGImageDecoder::frameComplete() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec7
886
    png_bytep interlaceBuffer = m_reader->interlaceBuffer();
884
    png_bytep interlaceBuffer = m_reader->interlaceBuffer();
887
885
888
    if (m_currentFrame && interlaceBuffer) {
886
    if (m_currentFrame && interlaceBuffer) {
889
        const IntRect& rect = buffer.originalFrameRect();
887
        const IntRect& rect = buffer.pixels()->rect();
890
        bool hasAlpha = m_reader->hasAlpha();
888
        bool hasAlpha = m_reader->hasAlpha();
891
        unsigned colorChannels = hasAlpha ? 4 : 3;
889
        unsigned colorChannels = hasAlpha ? 4 : 3;
892
        bool nonTrivialAlpha = false;
890
        bool nonTrivialAlpha = false;
Lines 896-902 void PNGImageDecoder::frameComplete() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec8
896
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
894
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
897
        for (int y = 0; y < rect.maxY() - rect.y(); ++y) {
895
        for (int y = 0; y < rect.maxY() - rect.y(); ++y) {
898
            png_bytep row = interlaceBuffer + (m_scaled ? m_scaledRows[y] : y) * colorChannels * size().width();
896
            png_bytep row = interlaceBuffer + (m_scaled ? m_scaledRows[y] : y) * colorChannels * size().width();
899
            ImageFrame::PixelData* address = buffer.getAddr(rect.x(), y + rect.y());
897
            RGBA32* address = buffer.getAddr(rect.x(), y + rect.y());
900
            for (int x = 0; x < rect.maxX() - rect.x(); ++x) {
898
            for (int x = 0; x < rect.maxX() - rect.x(); ++x) {
901
                png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
899
                png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
902
                unsigned alpha = hasAlpha ? pixel[3] : 255;
900
                unsigned alpha = hasAlpha ? pixel[3] : 255;
Lines 912-918 void PNGImageDecoder::frameComplete() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec9
912
        png_bytep row = interlaceBuffer;
910
        png_bytep row = interlaceBuffer;
913
        for (int y = rect.y(); y < rect.maxY(); ++y, row += colorChannels * size().width()) {
911
        for (int y = rect.y(); y < rect.maxY(); ++y, row += colorChannels * size().width()) {
914
            png_bytep pixel = row;
912
            png_bytep pixel = row;
915
            ImageFrame::PixelData* address = buffer.getAddr(rect.x(), y);
913
            RGBA32* address = buffer.getAddr(rect.x(), y);
916
            for (int x = rect.x(); x < rect.maxX(); ++x, pixel += colorChannels) {
914
            for (int x = rect.x(); x < rect.maxX(); ++x, pixel += colorChannels) {
917
                unsigned alpha = hasAlpha ? pixel[3] : 255;
915
                unsigned alpha = hasAlpha ? pixel[3] : 255;
918
                nonTrivialAlpha |= alpha < 255;
916
                nonTrivialAlpha |= alpha < 255;
Lines 925-931 void PNGImageDecoder::frameComplete() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec10
925
#endif
923
#endif
926
924
927
        if (!nonTrivialAlpha) {
925
        if (!nonTrivialAlpha) {
928
            if (buffer.originalFrameRect().contains(IntRect(IntPoint(), scaledSize())))
926
            if (buffer.pixels()->rect().contains(IntRect(IntPoint(), scaledSize())))
929
                buffer.setHasAlpha(false);
927
                buffer.setHasAlpha(false);
930
            else {
928
            else {
931
                size_t frameIndex = m_currentFrame;
929
                size_t frameIndex = m_currentFrame;
Lines 933-939 void PNGImageDecoder::frameComplete() a/Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec11
933
                while (frameIndex && (prevBuffer->disposalMethod() == ImageFrame::DisposeOverwritePrevious))
931
                while (frameIndex && (prevBuffer->disposalMethod() == ImageFrame::DisposeOverwritePrevious))
934
                    prevBuffer = &m_frameBufferCache[--frameIndex];
932
                    prevBuffer = &m_frameBufferCache[--frameIndex];
935
                if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor)
933
                if ((prevBuffer->disposalMethod() == ImageFrame::DisposeOverwriteBgcolor)
936
                    && !prevBuffer->hasAlpha() && buffer.originalFrameRect().contains(prevBuffer->originalFrameRect()))
934
                    && !prevBuffer->hasAlpha() && buffer.pixels()->rect().contains(prevBuffer->pixels()->rect()))
937
                    buffer.setHasAlpha(false);
935
                    buffer.setHasAlpha(false);
938
            }
936
            }
939
        } else if (!m_blend && !buffer.hasAlpha())
937
        } else if (!m_blend && !buffer.hasAlpha())
- a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp -2 / +1 lines
Lines 132-145 bool WEBPImageDecoder::decode(bool onlySize) a/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp_sec1
132
            return setFailed();
132
            return setFailed();
133
        buffer.setStatus(ImageFrame::FramePartial);
133
        buffer.setStatus(ImageFrame::FramePartial);
134
        buffer.setHasAlpha(m_hasAlpha);
134
        buffer.setHasAlpha(m_hasAlpha);
135
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
136
    }
135
    }
137
136
138
    if (!m_decoder) {
137
    if (!m_decoder) {
139
        WEBP_CSP_MODE mode = outputMode(m_hasAlpha);
138
        WEBP_CSP_MODE mode = outputMode(m_hasAlpha);
140
        if (!m_premultiplyAlpha)
139
        if (!m_premultiplyAlpha)
141
            mode = outputMode(false);
140
            mode = outputMode(false);
142
        int rowStride = size().width() * sizeof(ImageFrame::PixelData);
141
        int rowStride = size().width() * sizeof(RGBA32);
143
        uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0));
142
        uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0));
144
        int outputSize = size().height() * rowStride;
143
        int outputSize = size().height() * rowStride;
145
        m_decoder = WebPINewRGB(mode, output, outputSize, rowStride);
144
        m_decoder = WebPINewRGB(mode, output, outputSize, rowStride);

Return to Bug 159679