| Differences between
and this patch
- Source/WebCore/ChangeLog +102 lines
Lines 1-3 Source/WebCore/ChangeLog_sec1
1
2016-09-09  Said Abou-Hallawa  <sabouhallawa@apple.com>
2
3
        Move the pixel data of ImageFrame to a separate class named ImageBackingStore
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 allocate it on demand.
10
11
        * PlatformEfl.cmake:
12
        * PlatformGTK.cmake:
13
        * PlatformWinCairo.cmake:
14
        * WebCore.xcodeproj/project.pbxproj:
15
        * platform/graphics/Color.cpp:
16
        (WebCore::premultipliedChannel):
17
        (WebCore::unpremultipliedChannel):
18
        (WebCore::makePremultipliedRGBA):
19
        (WebCore::makeUnPremultipliedRGBA):
20
        (WebCore::colorFromPremultipliedARGB):
21
        (WebCore::premultipliedARGBFromColor):
22
        * platform/graphics/Color.h:
23
        (WebCore::fastMultiplyBy255):
24
        * platform/graphics/ImageBackingStore.h: Added.
25
        (WebCore::ImageBackingStore::create):
26
        (WebCore::ImageBackingStore::ImageBackingStore):
27
        (WebCore::ImageBackingStore::setSize):
28
        (WebCore::ImageBackingStore::setFrameRect):
29
        (WebCore::ImageBackingStore::size):
30
        (WebCore::ImageBackingStore::frameRect):
31
        (WebCore::ImageBackingStore::clear):
32
        (WebCore::ImageBackingStore::clearRect):
33
        (WebCore::ImageBackingStore::repeatFirstRow):
34
        (WebCore::ImageBackingStore::at):
35
        (WebCore::ImageBackingStore::setRGBA):
36
        (WebCore::ImageBackingStore::overRGBA):
37
        (WebCore::ImageBackingStore::inBounds):
38
        (WebCore::ImageBackingStore::isOverSize):
39
        * platform/graphics/cg/NativeImageCG.cpp:
40
        (WebCore::nativeImageHasAlpha):
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::setOriginalFrameRect):
49
        (WebCore::ImageDecoder::frameBytesAtIndex):
50
        * platform/image-decoders/ImageDecoder.h:
51
        (WebCore::ImageFrame::copyRowNTimes):
52
        (WebCore::ImageFrame::size):
53
        (WebCore::ImageFrame::asNewNativeImage):
54
        (WebCore::ImageFrame::backingStore):
55
        (WebCore::ImageFrame::hasBackingStore):
56
        (WebCore::ImageFrame::originalFrameRect):
57
        (WebCore::ImageFrame::getAddr):
58
        (WebCore::ImageFrame::setRGBA):
59
        (WebCore::ImageFrame::overRGBA):
60
        (WebCore::ImageDecoder::setSize):
61
        (WebCore::ImageFrame::setOriginalFrameRect): Deleted.
62
        (WebCore::ImageFrame::hasPixelData): Deleted.
63
        (WebCore::ImageFrame::fixPointUnsignedMultiply): Deleted.
64
        (WebCore::ImageFrame::divide255): Deleted.
65
        (WebCore::ImageFrame::width): Deleted.
66
        (WebCore::ImageFrame::height): Deleted.
67
        (WebCore::ImageDecoder::isOverSize): Deleted.
68
        * platform/image-decoders/bmp/BMPImageReader.cpp:
69
        (WebCore::BMPImageReader::decodeBMP):
70
        (WebCore::BMPImageReader::processInfoHeader):
71
        * platform/image-decoders/cairo/ImageBackingStoreCairo.cpp: Added.
72
        (WebCore::ImageBackingStore::image):
73
        * platform/image-decoders/gif/GIFImageDecoder.cpp:
74
        (WebCore::GIFImageDecoder::setSize):
75
        (WebCore::GIFImageDecoder::haveDecodedRow):
76
        (WebCore::GIFImageDecoder::initFrameBuffer):
77
        * platform/image-decoders/gif/GIFImageDecoder.h:
78
        * platform/image-decoders/gif/GIFImageReader.cpp:
79
        (GIFImageReader::parse):
80
        * platform/image-decoders/ico/ICOImageDecoder.cpp:
81
        (WebCore::ICOImageDecoder::setSize):
82
        (WebCore::ICOImageDecoder::processDirectoryEntries): Deleted.
83
        * platform/image-decoders/ico/ICOImageDecoder.h:
84
        * platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
85
        (WebCore::JPEGImageReader::decode):
86
        (WebCore::JPEGImageDecoder::setSize):
87
        (WebCore::setPixel):
88
        (WebCore::JPEGImageDecoder::outputScanlines):
89
        * platform/image-decoders/jpeg/JPEGImageDecoder.h:
90
        * platform/image-decoders/png/PNGImageDecoder.cpp:
91
        (WebCore::PNGImageDecoder::setSize):
92
        (WebCore::PNGImageDecoder::headerAvailable):
93
        (WebCore::setPixelRGB):
94
        (WebCore::setPixelRGBA):
95
        (WebCore::setPixelPremultipliedRGBA):
96
        (WebCore::PNGImageDecoder::rowAvailable):
97
        (WebCore::PNGImageDecoder::initFrameBuffer):
98
        (WebCore::PNGImageDecoder::frameComplete):
99
        * platform/image-decoders/png/PNGImageDecoder.h:
100
        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
101
        (WebCore::WEBPImageDecoder::decode):
102
1
2016-09-09  Commit Queue  <commit-queue@webkit.org>
103
2016-09-09  Commit Queue  <commit-queue@webkit.org>
2
104
3
        Unreviewed, rolling out r205771.
105
        Unreviewed, rolling out r205771.
- Source/WebCore/PlatformEfl.cmake -2 / +1 lines
Lines 183-192 list(APPEND WebCore_SOURCES Source/WebCore/PlatformEfl.cmake_sec1
183
    platform/graphics/x11/PlatformDisplayX11.cpp
183
    platform/graphics/x11/PlatformDisplayX11.cpp
184
    platform/graphics/x11/XUniqueResource.cpp
184
    platform/graphics/x11/XUniqueResource.cpp
185
185
186
    platform/image-decoders/cairo/ImageBackingStoreCairo.cpp
186
    platform/image-encoders/JPEGImageEncoder.cpp
187
    platform/image-encoders/JPEGImageEncoder.cpp
187
188
188
    platform/image-decoders/cairo/ImageDecoderCairo.cpp
189
190
    platform/network/efl/NetworkStateNotifierEfl.cpp
189
    platform/network/efl/NetworkStateNotifierEfl.cpp
191
190
192
    platform/network/soup/AuthenticationChallengeSoup.cpp
191
    platform/network/soup/AuthenticationChallengeSoup.cpp
- Source/WebCore/PlatformGTK.cmake -1 / +1 lines
Lines 155-161 list(APPEND WebCore_SOURCES Source/WebCore/PlatformGTK.cmake_sec1
155
    platform/gtk/TemporaryLinkStubs.cpp
155
    platform/gtk/TemporaryLinkStubs.cpp
156
    platform/gtk/UserAgentGtk.cpp
156
    platform/gtk/UserAgentGtk.cpp
157
157
158
    platform/image-decoders/cairo/ImageDecoderCairo.cpp
158
    platform/image-decoders/cairo/ImageBackingStoreCairo.cpp
159
159
160
    platform/mediastream/gtk/SDPProcessorScriptResourceGtk.cpp
160
    platform/mediastream/gtk/SDPProcessorScriptResourceGtk.cpp
161
161
- Source/WebCore/PlatformWinCairo.cmake -1 / +1 lines
Lines 46-52 list(APPEND WebCore_SOURCES 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/ImageBackingStoreCairo.cpp
50
50
51
    platform/network/NetworkStorageSessionStub.cpp
51
    platform/network/NetworkStorageSessionStub.cpp
52
52
- Source/WebCore/WebCore.xcodeproj/project.pbxproj +4 lines
Lines 2275-2280 Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
2275
		555B87EC1CAAF0AB00349425 /* ImageDecoderCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */; };
2275
		555B87EC1CAAF0AB00349425 /* ImageDecoderCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */; };
2276
		555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
2276
		555B87ED1CAAF0AB00349425 /* ImageDecoderCG.h in Headers */ = {isa = PBXBuildFile; fileRef = 555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */; };
2277
		55A336F71D8209F40022C4C7 /* NativeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F61D8209F40022C4C7 /* NativeImage.h */; };
2277
		55A336F71D8209F40022C4C7 /* NativeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F61D8209F40022C4C7 /* NativeImage.h */; };
2278
		55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */; settings = {ATTRIBUTES = (Private, ); }; };
2278
		5709E8CD1D413D47003244AC /* WebKitSubtleCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5709E8CA1D413CE3003244AC /* WebKitSubtleCrypto.cpp */; };
2279
		5709E8CD1D413D47003244AC /* WebKitSubtleCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5709E8CA1D413CE3003244AC /* WebKitSubtleCrypto.cpp */; };
2279
		5709E8CE1D413D5B003244AC /* JSWebKitSubtleCryptoCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF8F661807460800132674 /* JSWebKitSubtleCryptoCustom.cpp */; };
2280
		5709E8CE1D413D5B003244AC /* JSWebKitSubtleCryptoCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1FF8F661807460800132674 /* JSWebKitSubtleCryptoCustom.cpp */; };
2280
		5709E8CF1D413D9A003244AC /* WebKitSubtleCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 5709E8CB1D413CE3003244AC /* WebKitSubtleCrypto.h */; };
2281
		5709E8CF1D413D9A003244AC /* WebKitSubtleCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 5709E8CB1D413CE3003244AC /* WebKitSubtleCrypto.h */; };
Lines 9291-9296 Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
9291
		555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
9292
		555B87EA1CAAF0AB00349425 /* ImageDecoderCG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoderCG.cpp; sourceTree = "<group>"; };
9292
		555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
9293
		555B87EB1CAAF0AB00349425 /* ImageDecoderCG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoderCG.h; sourceTree = "<group>"; };
9293
		55A336F61D8209F40022C4C7 /* NativeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeImage.h; sourceTree = "<group>"; };
9294
		55A336F61D8209F40022C4C7 /* NativeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeImage.h; sourceTree = "<group>"; };
9295
		55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBackingStore.h; sourceTree = "<group>"; };
9294
		55D408F71A7C631800C78450 /* SVGImageClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageClients.h; sourceTree = "<group>"; };
9296
		55D408F71A7C631800C78450 /* SVGImageClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageClients.h; sourceTree = "<group>"; };
9295
		5709E8CA1D413CE3003244AC /* WebKitSubtleCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitSubtleCrypto.cpp; sourceTree = "<group>"; };
9297
		5709E8CA1D413CE3003244AC /* WebKitSubtleCrypto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebKitSubtleCrypto.cpp; sourceTree = "<group>"; };
9296
		5709E8CB1D413CE3003244AC /* WebKitSubtleCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitSubtleCrypto.h; sourceTree = "<group>"; };
9298
		5709E8CB1D413CE3003244AC /* WebKitSubtleCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitSubtleCrypto.h; sourceTree = "<group>"; };
Lines 20769-20774 Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
20769
				379919941200DDF400EA041C /* WOFFFileFormat.cpp */,
20771
				379919941200DDF400EA041C /* WOFFFileFormat.cpp */,
20770
				379919951200DDF400EA041C /* WOFFFileFormat.h */,
20772
				379919951200DDF400EA041C /* WOFFFileFormat.h */,
20771
				55A336F61D8209F40022C4C7 /* NativeImage.h */,
20773
				55A336F61D8209F40022C4C7 /* NativeImage.h */,
20774
				55A336F81D821E3C0022C4C7 /* ImageBackingStore.h */,
20772
			);
20775
			);
20773
			path = graphics;
20776
			path = graphics;
20774
			sourceTree = "<group>";
20777
			sourceTree = "<group>";
Lines 26339-26344 Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
26339
				582CB0531A78A14B00AFFCC4 /* SimpleLineLayoutTextFragmentIterator.h in Headers */,
26342
				582CB0531A78A14B00AFFCC4 /* SimpleLineLayoutTextFragmentIterator.h in Headers */,
26340
				C5A1EA7D152BCF08004D00B6 /* SimplifyMarkupCommand.h in Headers */,
26343
				C5A1EA7D152BCF08004D00B6 /* SimplifyMarkupCommand.h in Headers */,
26341
				572A7F211C6E5719009C6149 /* SimulatedClick.h in Headers */,
26344
				572A7F211C6E5719009C6149 /* SimulatedClick.h in Headers */,
26345
				55A336F91D821E3C0022C4C7 /* ImageBackingStore.h in Headers */,
26342
				31741AAD16636609008A5B7E /* SimulatedClickOptions.h in Headers */,
26346
				31741AAD16636609008A5B7E /* SimulatedClickOptions.h in Headers */,
26343
				FD00D7A514A3F61900734011 /* SincResampler.h in Headers */,
26347
				FD00D7A514A3F61900734011 /* SincResampler.h in Headers */,
26344
				51327D6011A33A2B004F9D65 /* SinkDocument.h in Headers */,
26348
				51327D6011A33A2B004F9D65 /* SinkDocument.h in Headers */,
- Source/WebCore/platform/graphics/Color.cpp -16 / +27 lines
Lines 49-54 const RGBA32 Color::transparent; 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 premultipliedChannel(unsigned c, unsigned a)
53
{
54
    return fastDivideBy255(c * a + 254);
55
}
56
57
static inline unsigned unpremultipliedChannel(unsigned c, unsigned a)
58
{
59
    return (fastMultiplyBy255(c) + a - 1) / a;
60
}
61
52
RGBA32 makeRGB(int r, int g, int b)
62
RGBA32 makeRGB(int r, int g, int b)
53
{
63
{
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));
64
    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 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));
69
    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
}
70
}
61
71
72
RGBA32 makePremultipliedRGBA(int r, int g, int b, int a)
73
{
74
    return makeRGBA(premultipliedChannel(r, a), premultipliedChannel(g, a), premultipliedChannel(b, a), a);
75
}
76
77
RGBA32 makeUnPremultipliedRGBA(int r, int g, int b, int a)
78
{
79
    return makeRGBA(unpremultipliedChannel(r, a), unpremultipliedChannel(g, a), unpremultipliedChannel(b, a), a);
80
}
81
62
static int colorFloatToRGBAByte(float f)
82
static int colorFloatToRGBAByte(float f)
63
{
83
{
64
    // We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
84
    // We use lroundf and 255 instead of nextafterf(256, 0) to match CG's rounding
Lines 482-495 void Color::getHSV(double& hue, double& Source/WebCore/platform/graphics/Color.cpp_sec3
482
Color colorFromPremultipliedARGB(RGBA32 pixelColor)
502
Color colorFromPremultipliedARGB(RGBA32 pixelColor)
483
{
503
{
484
    int alpha = alphaChannel(pixelColor);
504
    int alpha = alphaChannel(pixelColor);
485
    if (alpha && alpha < 255) {
505
    if (alpha && alpha < 255)
486
        return Color::createUnchecked(
506
        pixelColor = makeUnPremultipliedRGBA(redChannel(pixelColor), greenChannel(pixelColor), blueChannel(pixelColor), alpha);
487
            redChannel(pixelColor) * 255 / alpha,
507
    return Color(pixelColor);
488
            greenChannel(pixelColor) * 255 / alpha,
489
            blueChannel(pixelColor) * 255 / alpha,
490
            alpha);
491
    } else
492
        return Color(pixelColor);
493
}
508
}
494
509
495
RGBA32 premultipliedARGBFromColor(const Color& color)
510
RGBA32 premultipliedARGBFromColor(const Color& color)
Lines 497-510 RGBA32 premultipliedARGBFromColor(const Source/WebCore/platform/graphics/Color.cpp_sec4
497
    unsigned pixelColor;
512
    unsigned pixelColor;
498
513
499
    unsigned alpha = color.alpha();
514
    unsigned alpha = color.alpha();
500
    if (alpha < 255) {
515
    if (alpha < 255)
501
        pixelColor = Color::createUnchecked(
516
        pixelColor = makePremultipliedRGBA(color.red(), color.green(), color.blue(), alpha);
502
            fastDivideBy255(color.red() * alpha + 254),
517
    else
503
            fastDivideBy255(color.green() * alpha + 254),
518
        pixelColor = color.rgb();
504
            fastDivideBy255(color.blue() * alpha + 254),
505
            alpha).rgb();
506
    } else
507
         pixelColor = color.rgb();
508
519
509
    return pixelColor;
520
    return pixelColor;
510
}
521
}
- Source/WebCore/platform/graphics/Color.h +9 lines
Lines 55-60 typedef unsigned RGBA32; // Deprecated: Source/WebCore/platform/graphics/Color.h_sec1
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
57
58
RGBA32 makePremultipliedRGBA(int r, int g, int b, int a);
59
RGBA32 makeUnPremultipliedRGBA(int r, int g, int b, int a);
60
58
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, float overrideAlpha);
61
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, float overrideAlpha);
59
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, Optional<float> overrideAlpha);
62
WEBCORE_EXPORT RGBA32 colorWithOverrideAlpha(RGBA32 color, Optional<float> overrideAlpha);
60
63
Lines 218-223 Color blend(const Color& from, const Col Source/WebCore/platform/graphics/Color.h_sec2
218
221
219
int differenceSquared(const Color&, const Color&);
222
int differenceSquared(const Color&, const Color&);
220
223
224
uint16_t fastMultiplyBy255(uint16_t value);
221
uint16_t fastDivideBy255(uint16_t);
225
uint16_t fastDivideBy255(uint16_t);
222
226
223
#if USE(CG)
227
#if USE(CG)
Lines 290-295 inline uint8_t roundAndClampColorChannel Source/WebCore/platform/graphics/Color.h_sec3
290
    return std::max(0.f, std::min(255.f, std::round(value)));
294
    return std::max(0.f, std::min(255.f, std::round(value)));
291
}
295
}
292
296
297
inline uint16_t fastMultiplyBy255(uint16_t value)
298
{
299
    return (value << 8) - value;
300
}
301
293
inline uint16_t fastDivideBy255(uint16_t value)
302
inline uint16_t fastDivideBy255(uint16_t value)
294
{
303
{
295
    // While this is an approximate algorithm for division by 255, it gives perfectly accurate results for 16-bit values.
304
    // While this is an approximate algorithm for division by 255, it gives perfectly accurate results for 16-bit values.
- Source/WebCore/platform/graphics/ImageBackingStore.h +190 lines
Line 0 Source/WebCore/platform/graphics/ImageBackingStore.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 "NativeImage.h"
32
33
#include <wtf/Vector.h>
34
35
namespace WebCore {
36
37
class ImageBackingStore {
38
public:
39
    static std::unique_ptr<ImageBackingStore> create(const IntSize& size, bool premultiplyAlpha)
40
    {
41
        return std::make_unique<ImageBackingStore>(size, premultiplyAlpha);
42
    }
43
44
    static std::unique_ptr<ImageBackingStore> create(const ImageBackingStore& other)
45
    {
46
        return std::make_unique<ImageBackingStore>(other);
47
    }
48
49
    ImageBackingStore(const IntSize& size, bool premultiplyAlpha = true)
50
        : m_premultiplyAlpha(premultiplyAlpha)
51
    {
52
        ASSERT(!size.isEmpty());
53
        setSize(size);
54
    }
55
56
    ImageBackingStore(const ImageBackingStore& other)
57
    {
58
        if (this == &other)
59
            return;
60
61
        m_pixels = other.m_pixels;
62
        m_pixelsPtr = m_pixels.data();
63
        m_size = other.m_size;
64
        m_premultiplyAlpha = other.m_premultiplyAlpha;
65
    }
66
67
    NativeImagePtr image() const;
68
69
    bool setSize(const IntSize& size)
70
    {
71
        if (!m_pixels.tryReserveCapacity(size.area()))
72
            return false;
73
74
        m_pixels.resize(size.area());
75
        m_pixelsPtr = m_pixels.data();
76
        m_size = size;
77
        m_frameRect = IntRect(IntPoint(), m_size);
78
        clear();
79
        return true;
80
    }
81
82
    void setFrameRect(const IntRect& frameRect)
83
    {
84
        ASSERT(!m_size.isEmpty());
85
        ASSERT(inBounds(frameRect));
86
        m_frameRect = frameRect;
87
    }
88
89
    IntSize size() const { return m_size; }
90
    IntRect frameRect() const { return m_frameRect; }
91
92
    void clear()
93
    {
94
        memset(m_pixelsPtr, 0, m_size.area() * sizeof(RGBA32));
95
    }
96
97
    void clearRect(const IntRect& rect)
98
    {
99
        if (rect.isEmpty() || !inBounds(rect))
100
            return;
101
102
        size_t rectWidthInBytes = rect.width() * sizeof(RGBA32);
103
        RGBA32* start = at(rect.x(), rect.y());
104
        for (int i = 0; i < rect.height(); ++i) {
105
            memset(start, 0, rectWidthInBytes);
106
            start += m_size.width();
107
        }
108
    }
109
110
    void repeatFirstRow(const IntRect& rect)
111
    {
112
        if (rect.isEmpty() || !inBounds(rect))
113
            return;
114
115
        size_t rectWidthInBytes = rect.width() * sizeof(RGBA32);
116
        RGBA32* src = at(rect.x(), rect.y());
117
        RGBA32* dest = src + m_size.width();
118
        for (int i = 1; i < rect.height(); ++i) {
119
            memcpy(dest, src, rectWidthInBytes);
120
            dest += m_size.width();
121
        }
122
    }
123
124
    RGBA32* at(int x, int y) const
125
    {
126
        return m_pixelsPtr + y * m_size.width() + x;
127
    }
128
129
    void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
130
    {
131
        setRGBA(at(x, y), r, g, b, a);
132
    }
133
134
    void setRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
135
    {
136
        if (m_premultiplyAlpha && !a)
137
            *dest = 0;
138
        else if (m_premultiplyAlpha && a < 255)
139
            *dest = makePremultipliedRGBA(r, g, b, a);
140
        else
141
            *dest = makeRGBA(r, g, b, a);
142
    }
143
144
    void overRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
145
    {
146
        if (!a)
147
            return;
148
149
        if (a >= 255 || !alphaChannel(*dest)) {
150
            setRGBA(dest, r, g, b, a);
151
            return;
152
        }
153
154
        if (!m_premultiplyAlpha)
155
            *dest = makePremultipliedRGBA(redChannel(*dest), greenChannel(*dest), blueChannel(*dest), alphaChannel(*dest));
156
157
        unsigned d = 255 - a;
158
159
        r = fastDivideBy255(r * a + redChannel(*dest) * d);
160
        g = fastDivideBy255(g * a + greenChannel(*dest) * d);
161
        b = fastDivideBy255(b * a + blueChannel(*dest) * d);
162
        a += fastDivideBy255(d * alphaChannel(*dest));
163
164
        if (m_premultiplyAlpha)
165
            *dest = makeRGBA(r, g, b, a);
166
        else
167
            *dest = makeUnPremultipliedRGBA(r, g, b, a);
168
    }
169
170
    bool inBounds(const IntRect& rect) const
171
    {
172
        return IntRect(IntPoint(), m_size).contains(rect);
173
    }
174
175
    static bool isOverSize(const IntSize& size)
176
    {
177
        static unsigned long long MaxPixels = ((1 << 29) - 1);
178
        unsigned long long pixels = static_cast<unsigned long long>(size.width()) * static_cast<unsigned long long>(size.height());
179
        return pixels > MaxPixels;
180
    }
181
182
private:
183
    Vector<RGBA32> m_pixels;
184
    RGBA32* m_pixelsPtr { nullptr };
185
    IntSize m_size;
186
    IntRect m_frameRect; // This will always just be the entire buffer except for GIF and PNG frames
187
    bool m_premultiplyAlpha { true };
188
};
189
190
}
- Source/WebCore/platform/graphics/cg/NativeImageCG.cpp -3 / +3 lines
Lines 47-56 IntSize nativeImageSize(const NativeImag Source/WebCore/platform/graphics/cg/NativeImageCG.cpp_sec1
47
    return image ? IntSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get())) : IntSize();
47
    return image ? IntSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get())) : IntSize();
48
}
48
}
49
49
50
bool nativeImageHasAlpha(const NativeImagePtr&)
50
bool nativeImageHasAlpha(const NativeImagePtr& image)
51
{
51
{
52
    // FIXME: Answer correctly the question: does the CGImageRef have alpha channnel?
52
    CGImageAlphaInfo info = CGImageGetAlphaInfo(image.get());
53
    return true;
53
    return (info >= kCGImageAlphaPremultipliedLast) && (info <= kCGImageAlphaFirst);
54
}
54
}
55
55
56
Color nativeImageSinglePixelSolidColor(const NativeImagePtr& image)
56
Color nativeImageSinglePixelSolidColor(const NativeImagePtr& image)
- Source/WebCore/platform/image-decoders/ImageDecoder.cpp -29 / +20 lines
Lines 142-148 ImageFrame& ImageFrame::operator=(const 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 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_backingStore = 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() 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_backingStore->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_backingStore->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 Im 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_backingStore)
193
    m_bytes = m_backingStore.data();
184
        m_backingStore = ImageBackingStore::create(*other.m_backingStore.get());
194
    m_size = other.m_size;
185
    else
195
    setHasAlpha(other.m_hasAlpha);
186
        m_backingStore = nullptr;
187
    
196
    return true;
188
    return true;
197
}
189
}
198
190
199
bool ImageFrame::setSize(int newWidth, int newHeight)
191
bool ImageFrame::setSize(const IntSize& size)
200
{
192
{
201
    ASSERT(!width() && !height());
193
    ASSERT(!m_backingStore);
202
    size_t backingStoreSize = newWidth * newHeight;
194
    m_backingStore = ImageBackingStore::create(size, m_premultiplyAlpha);
203
    if (!m_backingStore.tryReserveCapacity(backingStoreSize))
195
    return m_backingStore != nullptr;
204
        return false;
205
    m_backingStore.resize(backingStoreSize);
206
    m_bytes = m_backingStore.data();
207
    m_size = IntSize(newWidth, newHeight);
208
209
    zeroFillPixelData();
210
    return true;
211
}
196
}
212
197
213
bool ImageFrame::hasAlpha() const
198
bool ImageFrame::hasAlpha() const
Lines 220-225 void ImageFrame::setHasAlpha(bool alpha) Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec5
220
    m_hasAlpha = alpha;
205
    m_hasAlpha = alpha;
221
}
206
}
222
207
208
void ImageFrame::setOriginalFrameRect(const IntRect& frameRect)
209
{
210
    if (m_backingStore)
211
        m_backingStore->setFrameRect(frameRect);
212
}
213
223
void ImageFrame::setStatus(FrameStatus status)
214
void ImageFrame::setStatus(FrameStatus status)
224
{
215
{
225
    m_status = status;
216
    m_status = status;
Lines 286-292 unsigned ImageDecoder::frameBytesAtIndex Source/WebCore/platform/image-decoders/ImageDecoder.cpp_sec6
286
    if (m_frameBufferCache.size() <= index)
277
    if (m_frameBufferCache.size() <= index)
287
        return 0;
278
        return 0;
288
    // FIXME: Use the dimension of the requested frame.
279
    // FIXME: Use the dimension of the requested frame.
289
    return m_size.area() * sizeof(ImageFrame::PixelData);
280
    return m_size.area() * sizeof(RGBA32);
290
}
281
}
291
282
292
float ImageDecoder::frameDurationAtIndex(size_t index)
283
float ImageDecoder::frameDurationAtIndex(size_t index)
- Source/WebCore/platform/image-decoders/ImageDecoder.h -112 / +26 lines
Lines 28-35 Source/WebCore/platform/image-decoders/ImageDecoder.h_sec1
28
28
29
#pragma once
29
#pragma once
30
30
31
#include "IntRect.h"
31
#include "ImageBackingStore.h"
32
#include "ImageSource.h"
32
#include "ImageSource.h"
33
#include "IntRect.h"
34
#include "IntSize.h"
33
#include "PlatformScreen.h"
35
#include "PlatformScreen.h"
34
#include "SharedBuffer.h"
36
#include "SharedBuffer.h"
35
#include <wtf/Assertions.h>
37
#include <wtf/Assertions.h>
Lines 57-63 using ColorProfile = Vector<char>; Source/WebCore/platform/image-decoders/ImageDecoder.h_sec2
57
            DisposeOverwritePrevious  // Clear frame to previous framebuffer
59
            DisposeOverwritePrevious  // Clear frame to previous framebuffer
58
                                      // contents
60
                                      // contents
59
        };
61
        };
60
        typedef unsigned PixelData;
61
62
62
        ImageFrame();
63
        ImageFrame();
63
64
Lines 82-223 using ColorProfile = Vector<char>; Source/WebCore/platform/image-decoders/ImageDecoder.h_sec3
82
        // endY.
83
        // endY.
83
        void copyRowNTimes(int startX, int endX, int startY, int endY)
84
        void copyRowNTimes(int startX, int endX, int startY, int endY)
84
        {
85
        {
85
            ASSERT(startX < width());
86
            m_backingStore->repeatFirstRow(IntRect(startX, startY, endX -startX , endY - startY));
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
        }
87
        }
94
88
95
        // Allocates space for the pixel data.  Must be called before any pixels
89
        // Allocates space for the pixel data.  Must be called before any pixels
96
        // are written.  Must only be called once.  Returns whether allocation
90
        // are written.  Must only be called once.  Returns whether allocation
97
        // succeeded.
91
        // succeeded.
98
        bool setSize(int newWidth, int newHeight);
92
        bool setSize(const IntSize&);
93
        IntSize size() const { return m_backingStore->size(); }
99
94
100
        // Returns a caller-owned pointer to the underlying native image data.
95
        // Returns a caller-owned pointer to the underlying native image data.
101
        // (Actual use: This pointer will be owned by BitmapImage and freed in
96
        // (Actual use: This pointer will be owned by BitmapImage and freed in
102
        // FrameData::clear()).
97
        // FrameData::clear()).
103
        NativeImagePtr asNewNativeImage() const;
98
        NativeImagePtr asNewNativeImage() const { return m_backingStore->image(); }
104
99
100
        inline ImageBackingStore* backingStore() const { return m_backingStore ? m_backingStore.get() : nullptr; }
101
        inline bool hasBackingStore() const { return backingStore(); }
102
        
105
        bool hasAlpha() const;
103
        bool hasAlpha() const;
106
        const IntRect& originalFrameRect() const { return m_originalFrameRect; }
104
        IntRect originalFrameRect() const { return m_backingStore ? m_backingStore->frameRect() : IntRect(); }
107
        FrameStatus status() const { return m_status; }
105
        FrameStatus status() const { return m_status; }
108
        unsigned duration() const { return m_duration; }
106
        unsigned duration() const { return m_duration; }
109
        FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
107
        FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
110
        bool premultiplyAlpha() const { return m_premultiplyAlpha; }
108
        bool premultiplyAlpha() const { return m_premultiplyAlpha; }
111
109
110
        void setBackingStore(const ImageBackingStore*);
111
        
112
        void setHasAlpha(bool alpha);
112
        void setHasAlpha(bool alpha);
113
        void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
113
        void setOriginalFrameRect(const IntRect&);
114
        void setStatus(FrameStatus status);
114
        void setStatus(FrameStatus status);
115
        void setDuration(unsigned duration) { m_duration = duration; }
115
        void setDuration(unsigned duration) { m_duration = duration; }
116
        void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
116
        void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
117
        void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
117
        void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
118
118
119
        inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
119
        inline RGBA32* getAddr(int x, int y)
120
        {
121
            setRGBA(getAddr(x, y), r, g, b, a);
122
        }
123
124
        inline PixelData* getAddr(int x, int y)
125
        {
126
            return m_bytes + (y * width()) + x;
127
        }
128
129
        inline bool hasPixelData() const
130
        {
120
        {
131
            return m_bytes;
121
            return m_backingStore->at(x, y);
132
        }
122
        }
133
123
134
        // Use fix point multiplier instead of integer division or floating point math.
124
        inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
135
        // This multipler produces exactly the same result for all values in range 0 - 255.
136
        static const unsigned fixPointShift = 24;
137
        static const unsigned fixPointMult = static_cast<unsigned>(1.0 / 255.0 * (1 << fixPointShift)) + 1;
138
        // Multiplies unsigned value by fixpoint value and converts back to unsigned.
139
        static unsigned fixPointUnsignedMultiply(unsigned fixed, unsigned v)
140
        {
125
        {
141
            return  (fixed * v) >> fixPointShift;
126
            m_backingStore->setRGBA(x, y, r, g, b, a);
142
        }
127
        }
143
128
144
        inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
129
        inline void setRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
145
        {
130
        {
146
            if (m_premultiplyAlpha && a < 255) {
131
            m_backingStore->setRGBA(dest, r, g, b, a);
147
                if (!a) {
148
                    *dest = 0;
149
                    return;
150
                }
151
152
                unsigned alphaMult = a * fixPointMult;
153
                r = fixPointUnsignedMultiply(r, alphaMult);
154
                g = fixPointUnsignedMultiply(g, alphaMult);
155
                b = fixPointUnsignedMultiply(b, alphaMult);
156
            }
157
            *dest = (a << 24 | r << 16 | g << 8 | b);
158
        }
132
        }
159
133
160
#if ENABLE(APNG)
134
#if ENABLE(APNG)
161
        static inline unsigned divide255(unsigned a)
135
        inline void overRGBA(RGBA32* dest, unsigned r, unsigned g, unsigned b, unsigned a)
162
        {
136
        {
163
            return (a + (a >> 8) + 1) >> 8;
137
            m_backingStore->overRGBA(dest, r, g, b, a);
164
        }
165
166
        inline void overRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
167
        {
168
            if (!a)
169
                return;
170
171
            if (a < 255) {
172
                unsigned aDest = ((*dest) >> 24) & 255;
173
                if (aDest) {
174
                    unsigned rDest = ((*dest) >> 16) & 255;
175
                    unsigned gDest = ((*dest) >> 8) & 255;
176
                    unsigned bDest = (*dest) & 255;
177
                    unsigned aAux = 255 - a;
178
                    if (!m_premultiplyAlpha) {
179
                        rDest = divide255(rDest * aDest);
180
                        gDest = divide255(gDest * aDest);
181
                        bDest = divide255(bDest * aDest);
182
                    }
183
                    r = divide255(r * a + rDest * aAux);
184
                    g = divide255(g * a + gDest * aAux);
185
                    b = divide255(b * a + bDest * aAux);
186
                    a += divide255(aDest * aAux);
187
                    if (!m_premultiplyAlpha) {
188
                        r = (r * 255 + a - 1) / a;
189
                        g = (g * 255 + a - 1) / a;
190
                        b = (b * 255 + a - 1) / a;
191
                    }
192
                } else if (m_premultiplyAlpha) {
193
                    r = divide255(r * a);
194
                    g = divide255(g * a);
195
                    b = divide255(b * a);
196
                }
197
            }
198
            *dest = (a << 24 | r << 16 | g << 8 | b);
199
        }
138
        }
200
#endif
139
#endif
201
140
202
    private:
141
    private:
203
        int width() const
142
        std::unique_ptr<ImageBackingStore> m_backingStore;
204
        {
205
            return m_size.width();
206
        }
207
208
        int height() const
209
        {
210
            return m_size.height();
211
        }
212
213
        Vector<PixelData> m_backingStore;
214
        PixelData* m_bytes; // The memory is backed by m_backingStore.
215
        IntSize m_size;
216
        bool m_hasAlpha;
143
        bool m_hasAlpha;
217
        IntRect m_originalFrameRect; // This will always just be the entire
218
                                     // buffer except for GIF frames whose
219
                                     // original rect was smaller than the
220
                                     // overall image size.
221
        FrameStatus m_status;
144
        FrameStatus m_status;
222
        unsigned m_duration;
145
        unsigned m_duration;
223
        FrameDisposalMethod m_disposalMethod;
146
        FrameDisposalMethod m_disposalMethod;
Lines 287-297 using ColorProfile = Vector<char>; Source/WebCore/platform/image-decoders/ImageDecoder.h_sec4
287
210
288
        // Returns whether the size is legal (i.e. not going to result in
211
        // Returns whether the size is legal (i.e. not going to result in
289
        // overflow elsewhere).  If not, marks decoding as failed.
212
        // overflow elsewhere).  If not, marks decoding as failed.
290
        virtual bool setSize(unsigned width, unsigned height)
213
        virtual bool setSize(const IntSize& size)
291
        {
214
        {
292
            if (isOverSize(width, height))
215
            if (ImageBackingStore::isOverSize(size))
293
                return setFailed();
216
                return setFailed();
294
            m_size = IntSize(width, height);
217
            m_size = size;
295
            m_sizeAvailable = true;
218
            m_sizeAvailable = true;
296
            return true;
219
            return true;
297
        }
220
        }
Lines 386-400 using ColorProfile = Vector<char>; Source/WebCore/platform/image-decoders/ImageDecoder.h_sec5
386
        ImageOrientation m_orientation;
309
        ImageOrientation m_orientation;
387
310
388
    private:
311
    private:
389
        // Some code paths compute the size of the image as "width * height * 4"
390
        // and return it as a (signed) int.  Avoid overflow.
391
        static bool isOverSize(unsigned width, unsigned height)
392
        {
393
            unsigned long long total_size = static_cast<unsigned long long>(width)
394
                                          * static_cast<unsigned long long>(height);
395
            return total_size > ((1 << 29) - 1);
396
        }
397
398
        IntSize m_size;
312
        IntSize m_size;
399
        bool m_sizeAvailable { false };
313
        bool m_sizeAvailable { false };
400
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
314
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
- Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp -5 / +2 lines
Lines 78-84 bool BMPImageReader::decodeBMP(bool only Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp_sec1
78
    // Initialize the framebuffer if needed.
78
    // Initialize the framebuffer if needed.
79
    ASSERT(m_buffer);  // Parent should set this before asking us to decode!
79
    ASSERT(m_buffer);  // Parent should set this before asking us to decode!
80
    if (m_buffer->status() == ImageFrame::FrameEmpty) {
80
    if (m_buffer->status() == ImageFrame::FrameEmpty) {
81
        if (!m_buffer->setSize(m_parent->size().width(), m_parent->size().height()))
81
        if (!m_buffer->setSize(m_parent->size()))
82
            return m_parent->setFailed(); // Unable to allocate.
82
            return m_parent->setFailed(); // Unable to allocate.
83
        m_buffer->setStatus(ImageFrame::FramePartial);
83
        m_buffer->setStatus(ImageFrame::FramePartial);
84
        // setSize() calls eraseARGB(), which resets the alpha flag, so we force
84
        // setSize() calls eraseARGB(), which resets the alpha flag, so we force
Lines 86-94 bool BMPImageReader::decodeBMP(bool only Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp_sec2
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
    }
Lines 171-177 bool BMPImageReader::processInfoHeader() Source/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp_sec3
171
        return m_parent->setFailed();
168
        return m_parent->setFailed();
172
169
173
    // Set our size.
170
    // Set our size.
174
    if (!m_parent->setSize(m_infoHeader.biWidth, m_infoHeader.biHeight))
171
    if (!m_parent->setSize(IntSize(m_infoHeader.biWidth, m_infoHeader.biHeight)))
175
        return false;
172
        return false;
176
173
177
    // For paletted images, bitmaps can set biClrUsed to 0 to mean "all
174
    // For paletted images, bitmaps can set biClrUsed to 0 to mean "all
- Source/WebCore/platform/image-decoders/cairo/ImageBackingStoreCairo.cpp +40 lines
Line 0 Source/WebCore/platform/image-decoders/cairo/ImageBackingStoreCairo.cpp_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
#include "config.h"
27
#include "ImageBackingStore.h"
28
29
#include <cairo.h>
30
31
namespace WebCore {
32
33
NativeImagePtr ImageBackingStore::image() const
34
{
35
    return adoptRef(cairo_image_surface_create_for_data(
36
        reinterpret_cast<unsigned char*>(const_cast<RGBA32*>(m_pixelsPtr)),
37
        CAIRO_FORMAT_ARGB32, size().width(), size().height(), size().width() * sizeof(RGBA32)));
38
}
39
40
} // namespace WebCore
- Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp -8 / +8 lines
Lines 60-71 bool GIFImageDecoder::isSizeAvailable() Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec1
60
    return ImageDecoder::isSizeAvailable();
60
    return ImageDecoder::isSizeAvailable();
61
}
61
}
62
62
63
bool GIFImageDecoder::setSize(unsigned width, unsigned height)
63
bool GIFImageDecoder::setSize(const IntSize& size)
64
{
64
{
65
    if (ImageDecoder::isSizeAvailable() && size() == IntSize(width, height))
65
    if (ImageDecoder::isSizeAvailable() && this->size() == size)
66
        return true;
66
        return true;
67
67
68
    if (!ImageDecoder::setSize(width, height))
68
    if (!ImageDecoder::setSize(size))
69
        return false;
69
        return false;
70
70
71
    prepareScaleDataIfNecessary();
71
    prepareScaleDataIfNecessary();
Lines 213-222 bool GIFImageDecoder::haveDecodedRow(uns Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec2
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.hasBackingStore())
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 361-367 bool GIFImageDecoder::initFrameBuffer(un Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec3
361
361
362
    if (!frameIndex) {
362
    if (!frameIndex) {
363
        // This is the first frame, so we're not relying on any previous data.
363
        // This is the first frame, so we're not relying on any previous data.
364
        if (!buffer->setSize(scaledSize().width(), scaledSize().height()))
364
        if (!buffer->setSize(scaledSize()))
365
            return setFailed();
365
            return setFailed();
366
    } else {
366
    } else {
367
        // The starting state for this frame depends on the previous frame's
367
        // The starting state for this frame depends on the previous frame's
Lines 387-398 bool GIFImageDecoder::initFrameBuffer(un Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp_sec4
387
        } else {
387
        } else {
388
            // We want to clear the previous frame to transparent, without
388
            // We want to clear the previous frame to transparent, without
389
            // affecting pixels in the image outside of the frame.
389
            // affecting pixels in the image outside of the frame.
390
            const IntRect& prevRect = prevBuffer->originalFrameRect();
390
            IntRect prevRect = prevBuffer->originalFrameRect();
391
            const IntSize& bufferSize = scaledSize();
391
            const IntSize& bufferSize = scaledSize();
392
            if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
392
            if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
393
                // Clearing the first frame, or a frame the size of the whole
393
                // Clearing the first frame, or a frame the size of the whole
394
                // image, results in a completely empty image.
394
                // image, results in a completely empty image.
395
                if (!buffer->setSize(bufferSize.width(), bufferSize.height()))
395
                if (!buffer->setSize(bufferSize))
396
                    return setFailed();
396
                    return setFailed();
397
            } else {
397
            } else {
398
                // Copy the whole previous buffer, then clear just its frame.
398
                // Copy the whole previous buffer, then clear just its frame.
- Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h -1 / +1 lines
Lines 44-50 namespace WebCore { Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h_sec1
44
        String filenameExtension() const override { return "gif"; }
44
        String filenameExtension() const override { return "gif"; }
45
        void setData(SharedBuffer& data, bool allDataReceived) override;
45
        void setData(SharedBuffer& data, bool allDataReceived) override;
46
        bool isSizeAvailable() override;
46
        bool isSizeAvailable() override;
47
        bool setSize(unsigned width, unsigned height) override;
47
        bool setSize(const IntSize&) override;
48
        size_t frameCount() override;
48
        size_t frameCount() override;
49
        int repetitionCount() const override;
49
        int repetitionCount() const override;
50
        ImageFrame* frameBufferAtIndex(size_t index) override;
50
        ImageFrame* frameBufferAtIndex(size_t index) override;
- Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp -2 / +2 lines
Lines 447-453 bool GIFImageReader::parse(size_t dataPo Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp_sec1
447
447
448
            // CALLBACK: Inform the decoderplugin of our size.
448
            // CALLBACK: Inform the decoderplugin of our size.
449
            // Note: A subsequent frame might have dimensions larger than the "screen" dimensions.
449
            // Note: A subsequent frame might have dimensions larger than the "screen" dimensions.
450
            if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
450
            if (m_client && !m_client->setSize(WebCore::IntSize(m_screenWidth, m_screenHeight)))
451
                return false;
451
                return false;
452
452
453
            m_screenBgcolor = currentComponent[5];
453
            m_screenBgcolor = currentComponent[5];
Lines 664-670 bool GIFImageReader::parse(size_t dataPo Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp_sec2
664
                yOffset = 0;
664
                yOffset = 0;
665
665
666
                // CALLBACK: Inform the decoderplugin of our size.
666
                // CALLBACK: Inform the decoderplugin of our size.
667
                if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
667
                if (m_client && !m_client->setSize(WebCore::IntSize(m_screenWidth, m_screenHeight)))
668
                    return false;
668
                    return false;
669
            }
669
            }
670
670
- Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp -3 / +3 lines
Lines 88-98 IntSize ICOImageDecoder::frameSizeAtInde Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp_sec1
88
    return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size();
88
    return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size();
89
}
89
}
90
90
91
bool ICOImageDecoder::setSize(unsigned width, unsigned height)
91
bool ICOImageDecoder::setSize(const IntSize& size)
92
{
92
{
93
    // The size calculated inside the BMPImageReader had better match the one in
93
    // The size calculated inside the BMPImageReader had better match the one in
94
    // the icon directory.
94
    // the icon directory.
95
    return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntSize(width, height) == m_frameSize) || setFailed());
95
    return m_frameSize.isEmpty() ? ImageDecoder::setSize(size) : ((size == m_frameSize) || setFailed());
96
}
96
}
97
97
98
size_t ICOImageDecoder::frameCount()
98
size_t ICOImageDecoder::frameCount()
Lines 279-285 bool ICOImageDecoder::processDirectoryEn Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp_sec2
279
    const IconDirectoryEntry& dirEntry = m_dirEntries.first();
279
    const IconDirectoryEntry& dirEntry = m_dirEntries.first();
280
    // Technically, this next call shouldn't be able to fail, since the width
280
    // Technically, this next call shouldn't be able to fail, since the width
281
    // and height here are each <= 256, and |m_frameSize| is empty.
281
    // and height here are each <= 256, and |m_frameSize| is empty.
282
    return setSize(dirEntry.m_size.width(), dirEntry.m_size.height());
282
    return setSize(dirEntry.m_size);
283
}
283
}
284
284
285
ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry()
285
ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry()
- Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h -1 / +1 lines
Lines 49-55 namespace WebCore { Source/WebCore/platform/image-decoders/ico/ICOImageDecoder.h_sec1
49
        bool isSizeAvailable() override;
49
        bool isSizeAvailable() override;
50
        IntSize size() override;
50
        IntSize size() override;
51
        IntSize frameSizeAtIndex(size_t, SubsamplingLevel) override;
51
        IntSize frameSizeAtIndex(size_t, SubsamplingLevel) override;
52
        bool setSize(unsigned width, unsigned height) override;
52
        bool setSize(const IntSize&) override;
53
        size_t frameCount() override;
53
        size_t frameCount() override;
54
        ImageFrame* frameBufferAtIndex(size_t) override;
54
        ImageFrame* frameBufferAtIndex(size_t) override;
55
        // CAUTION: setFailed() deletes all readers and decoders.  Be careful to
55
        // CAUTION: setFailed() deletes all readers and decoders.  Be careful to
- Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp -9 / +6 lines
Lines 322-328 public: Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec1
322
            m_state = JPEG_START_DECOMPRESS;
322
            m_state = JPEG_START_DECOMPRESS;
323
323
324
            // We can fill in the size now that the header is available.
324
            // We can fill in the size now that the header is available.
325
            if (!m_decoder->setSize(m_info.image_width, m_info.image_height))
325
            if (!m_decoder->setSize(IntSize(m_info.image_width, m_info.image_height)))
326
                return false;
326
                return false;
327
327
328
            m_decoder->setOrientation(readImageOrientation(info()));
328
            m_decoder->setOrientation(readImageOrientation(info()));
Lines 519-527 bool JPEGImageDecoder::isSizeAvailable() Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec2
519
    return ImageDecoder::isSizeAvailable();
519
    return ImageDecoder::isSizeAvailable();
520
}
520
}
521
521
522
bool JPEGImageDecoder::setSize(unsigned width, unsigned height)
522
bool JPEGImageDecoder::setSize(const IntSize& size)
523
{
523
{
524
    if (!ImageDecoder::setSize(width, height))
524
    if (!ImageDecoder::setSize(size))
525
        return false;
525
        return false;
526
526
527
    prepareScaleDataIfNecessary();
527
    prepareScaleDataIfNecessary();
Lines 551-557 bool JPEGImageDecoder::setFailed() Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec3
551
}
551
}
552
552
553
template <J_COLOR_SPACE colorSpace>
553
template <J_COLOR_SPACE colorSpace>
554
void setPixel(ImageFrame& buffer, ImageFrame::PixelData* currentAddress, JSAMPARRAY samples, int column)
554
void setPixel(ImageFrame& buffer, RGBA32* currentAddress, JSAMPARRAY samples, int column)
555
{
555
{
556
    JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4);
556
    JSAMPLE* jsample = *samples + column * (colorSpace == JCS_RGB ? 3 : 4);
557
557
Lines 594-600 bool JPEGImageDecoder::outputScanlines(I Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec4
594
        if (destY < 0)
594
        if (destY < 0)
595
            continue;
595
            continue;
596
596
597
        ImageFrame::PixelData* currentAddress = buffer.getAddr(0, destY);
597
        RGBA32* currentAddress = buffer.getAddr(0, destY);
598
        for (int x = 0; x < width; ++x) {
598
        for (int x = 0; x < width; ++x) {
599
            setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
599
            setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
600
            ++currentAddress;
600
            ++currentAddress;
Lines 617-631 bool JPEGImageDecoder::outputScanlines() Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp_sec5
617
    // Initialize the framebuffer if needed.
617
    // Initialize the framebuffer if needed.
618
    ImageFrame& buffer = m_frameBufferCache[0];
618
    ImageFrame& buffer = m_frameBufferCache[0];
619
    if (buffer.status() == ImageFrame::FrameEmpty) {
619
    if (buffer.status() == ImageFrame::FrameEmpty) {
620
        if (!buffer.setSize(scaledSize().width(), scaledSize().height()))
620
        if (!buffer.setSize(scaledSize()))
621
            return setFailed();
621
            return setFailed();
622
        buffer.setStatus(ImageFrame::FramePartial);
622
        buffer.setStatus(ImageFrame::FramePartial);
623
        // The buffer is transparent outside the decoded area while the image is
623
        // The buffer is transparent outside the decoded area while the image is
624
        // loading. The completed image will be marked fully opaque in jpegComplete().
624
        // loading. The completed image will be marked fully opaque in jpegComplete().
625
        buffer.setHasAlpha(true);
625
        buffer.setHasAlpha(true);
626
627
        // For JPEGs, the frame always fills the entire image.
628
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
629
    }
626
    }
630
627
631
    jpeg_decompress_struct* info = m_reader->info();
628
    jpeg_decompress_struct* info = m_reader->info();
- Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h -1 / +1 lines
Lines 50-56 namespace WebCore { Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h_sec1
50
        // ImageDecoder
50
        // ImageDecoder
51
        String filenameExtension() const override { return "jpg"; }
51
        String filenameExtension() const override { return "jpg"; }
52
        bool isSizeAvailable() override;
52
        bool isSizeAvailable() override;
53
        bool setSize(unsigned width, unsigned height) override;
53
        bool setSize(const IntSize&) override;
54
        ImageFrame* frameBufferAtIndex(size_t index) override;
54
        ImageFrame* frameBufferAtIndex(size_t index) override;
55
        // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
55
        // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
56
        // accessing deleted memory, especially when calling this from inside
56
        // accessing deleted memory, especially when calling this from inside
- Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp -15 / +12 lines
Lines 235-243 bool PNGImageDecoder::isSizeAvailable() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec1
235
    return ImageDecoder::isSizeAvailable();
235
    return ImageDecoder::isSizeAvailable();
236
}
236
}
237
237
238
bool PNGImageDecoder::setSize(unsigned width, unsigned height)
238
bool PNGImageDecoder::setSize(const IntSize& size)
239
{
239
{
240
    if (!ImageDecoder::setSize(width, height))
240
    if (!ImageDecoder::setSize(size))
241
        return false;
241
        return false;
242
242
243
    prepareScaleDataIfNecessary();
243
    prepareScaleDataIfNecessary();
Lines 295-301 void PNGImageDecoder::headerAvailable() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec2
295
    // will cease to exist.  Note that we'll still properly set the failure flag
295
    // will cease to exist.  Note that we'll still properly set the failure flag
296
    // in this case as soon as we longjmp().
296
    // in this case as soon as we longjmp().
297
    m_doNothingOnFailure = true;
297
    m_doNothingOnFailure = true;
298
    bool result = setSize(width, height);
298
    bool result = setSize(IntSize(width, height));
299
    m_doNothingOnFailure = false;
299
    m_doNothingOnFailure = false;
300
    if (!result) {
300
    if (!result) {
301
        longjmp(JMPBUF(png), 1);
301
        longjmp(JMPBUF(png), 1);
Lines 411-429 void PNGImageDecoder::headerAvailable() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec3
411
    }
411
    }
412
}
412
}
413
413
414
static inline void setPixelRGB(ImageFrame::PixelData* dest, png_bytep pixel)
414
static inline void setPixelRGB(RGBA32* dest, png_bytep pixel)
415
{
415
{
416
    *dest = 0xFF000000U | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
416
    *dest = 0xFF000000U | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
417
}
417
}
418
418
419
static inline void setPixelRGBA(ImageFrame::PixelData* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
419
static inline void setPixelRGBA(RGBA32* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
420
{
420
{
421
    unsigned char a = pixel[3];
421
    unsigned char a = pixel[3];
422
    *dest = a << 24 | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
422
    *dest = a << 24 | pixel[0] << 16 | pixel[1] << 8 | pixel[2];
423
    nonTrivialAlphaMask |= (255 - a);
423
    nonTrivialAlphaMask |= (255 - a);
424
}
424
}
425
425
426
static inline void setPixelPremultipliedRGBA(ImageFrame::PixelData* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
426
static inline void setPixelPremultipliedRGBA(RGBA32* dest, png_bytep pixel, unsigned char& nonTrivialAlphaMask)
427
{
427
{
428
    unsigned char a = pixel[3];
428
    unsigned char a = pixel[3];
429
    unsigned char r = fastDivideBy255(pixel[0] * a);
429
    unsigned char r = fastDivideBy255(pixel[0] * a);
Lines 447-453 void PNGImageDecoder::rowAvailable(unsig Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec4
447
    ImageFrame& buffer = m_frameBufferCache[m_currentFrame];
447
    ImageFrame& buffer = m_frameBufferCache[m_currentFrame];
448
    if (buffer.status() == ImageFrame::FrameEmpty) {
448
    if (buffer.status() == ImageFrame::FrameEmpty) {
449
        png_structp png = m_reader->pngPtr();
449
        png_structp png = m_reader->pngPtr();
450
        if (!buffer.setSize(scaledSize().width(), scaledSize().height())) {
450
        if (!buffer.setSize(scaledSize())) {
451
            longjmp(JMPBUF(png), 1);
451
            longjmp(JMPBUF(png), 1);
452
            return;
452
            return;
453
        }
453
        }
Lines 469-478 void PNGImageDecoder::rowAvailable(unsig Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec5
469
#if ENABLE(APNG)
469
#if ENABLE(APNG)
470
        if (m_currentFrame)
470
        if (m_currentFrame)
471
            initFrameBuffer(m_currentFrame);
471
            initFrameBuffer(m_currentFrame);
472
        else
473
#endif
472
#endif
474
        // For PNGs, the frame always fills the entire image.
475
        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
476
    }
473
    }
477
474
478
    /* libpng comments (here to explain what follows).
475
    /* libpng comments (here to explain what follows).
Lines 531-537 void PNGImageDecoder::rowAvailable(unsig Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec6
531
    }
528
    }
532
529
533
    // Write the decoded row pixels to the frame buffer.
530
    // Write the decoded row pixels to the frame buffer.
534
    ImageFrame::PixelData* address = buffer.getAddr(0, y);
531
    RGBA32* address = buffer.getAddr(0, y);
535
    int width = scaledSize().width();
532
    int width = scaledSize().width();
536
    unsigned char nonTrivialAlphaMask = 0;
533
    unsigned char nonTrivialAlphaMask = 0;
537
534
Lines 820-826 void PNGImageDecoder::initFrameBuffer(si Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec7
820
    } else {
817
    } else {
821
        // We want to clear the previous frame to transparent, without
818
        // We want to clear the previous frame to transparent, without
822
        // affecting pixels in the image outside of the frame.
819
        // affecting pixels in the image outside of the frame.
823
        const IntRect& prevRect = prevBuffer->originalFrameRect();
820
        IntRect prevRect = prevBuffer->originalFrameRect();
824
        if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
821
        if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) {
825
            // Clearing the first frame, or a frame the size of the whole
822
            // Clearing the first frame, or a frame the size of the whole
826
            // image, results in a completely empty image.
823
            // image, results in a completely empty image.
Lines 844-850 void PNGImageDecoder::frameComplete() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec8
844
    png_bytep interlaceBuffer = m_reader->interlaceBuffer();
841
    png_bytep interlaceBuffer = m_reader->interlaceBuffer();
845
842
846
    if (m_currentFrame && interlaceBuffer) {
843
    if (m_currentFrame && interlaceBuffer) {
847
        const IntRect& rect = buffer.originalFrameRect();
844
        IntRect rect = buffer.originalFrameRect();
848
        bool hasAlpha = m_reader->hasAlpha();
845
        bool hasAlpha = m_reader->hasAlpha();
849
        unsigned colorChannels = hasAlpha ? 4 : 3;
846
        unsigned colorChannels = hasAlpha ? 4 : 3;
850
        bool nonTrivialAlpha = false;
847
        bool nonTrivialAlpha = false;
Lines 854-860 void PNGImageDecoder::frameComplete() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec9
854
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
851
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
855
        for (int y = 0; y < rect.maxY() - rect.y(); ++y) {
852
        for (int y = 0; y < rect.maxY() - rect.y(); ++y) {
856
            png_bytep row = interlaceBuffer + (m_scaled ? m_scaledRows[y] : y) * colorChannels * size().width();
853
            png_bytep row = interlaceBuffer + (m_scaled ? m_scaledRows[y] : y) * colorChannels * size().width();
857
            ImageFrame::PixelData* address = buffer.getAddr(rect.x(), y + rect.y());
854
            RGBA32* address = buffer.getAddr(rect.x(), y + rect.y());
858
            for (int x = 0; x < rect.maxX() - rect.x(); ++x) {
855
            for (int x = 0; x < rect.maxX() - rect.x(); ++x) {
859
                png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
856
                png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels;
860
                unsigned alpha = hasAlpha ? pixel[3] : 255;
857
                unsigned alpha = hasAlpha ? pixel[3] : 255;
Lines 870-876 void PNGImageDecoder::frameComplete() Source/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp_sec10
870
        png_bytep row = interlaceBuffer;
867
        png_bytep row = interlaceBuffer;
871
        for (int y = rect.y(); y < rect.maxY(); ++y, row += colorChannels * size().width()) {
868
        for (int y = rect.y(); y < rect.maxY(); ++y, row += colorChannels * size().width()) {
872
            png_bytep pixel = row;
869
            png_bytep pixel = row;
873
            ImageFrame::PixelData* address = buffer.getAddr(rect.x(), y);
870
            RGBA32* address = buffer.getAddr(rect.x(), y);
874
            for (int x = rect.x(); x < rect.maxX(); ++x, pixel += colorChannels) {
871
            for (int x = rect.x(); x < rect.maxX(); ++x, pixel += colorChannels) {
875
                unsigned alpha = hasAlpha ? pixel[3] : 255;
872
                unsigned alpha = hasAlpha ? pixel[3] : 255;
876
                nonTrivialAlpha |= alpha < 255;
873
                nonTrivialAlpha |= alpha < 255;
- Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h -1 / +1 lines
Lines 48-54 namespace WebCore { Source/WebCore/platform/image-decoders/png/PNGImageDecoder.h_sec1
48
        int repetitionCount() const override { return m_playCount-1; }
48
        int repetitionCount() const override { return m_playCount-1; }
49
#endif
49
#endif
50
        bool isSizeAvailable() override;
50
        bool isSizeAvailable() override;
51
        bool setSize(unsigned width, unsigned height) override;
51
        bool setSize(const IntSize&) override;
52
        ImageFrame* frameBufferAtIndex(size_t index) override;
52
        ImageFrame* frameBufferAtIndex(size_t index) override;
53
        // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
53
        // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
54
        // accessing deleted memory, especially when calling this from inside
54
        // accessing deleted memory, especially when calling this from inside
- Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp -4 / +3 lines
Lines 115-121 bool WEBPImageDecoder::decode(bool onlyS Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp_sec1
115
            return setFailed();
115
            return setFailed();
116
        m_hasAlpha = false;
116
        m_hasAlpha = false;
117
#endif
117
#endif
118
        if (!setSize(width, height))
118
        if (!setSize(IntSize(width, height)))
119
            return setFailed();
119
            return setFailed();
120
    }
120
    }
121
121
Lines 128-145 bool WEBPImageDecoder::decode(bool onlyS Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp_sec2
128
    ASSERT(buffer.status() != ImageFrame::FrameComplete);
128
    ASSERT(buffer.status() != ImageFrame::FrameComplete);
129
129
130
    if (buffer.status() == ImageFrame::FrameEmpty) {
130
    if (buffer.status() == ImageFrame::FrameEmpty) {
131
        if (!buffer.setSize(size().width(), size().height()))
131
        if (!buffer.setSize(size()))
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