Source/WebCore/ChangeLog

 12017-12-30 Simon Fraser <simon.fraser@apple.com>
 2
 3 SVG lighting colors need to be converted into linearSRGB
 4 https://bugs.webkit.org/show_bug.cgi?id=181196
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 SVG filters, like feLighting, that poke values directly into buffers rather than going
 9 through CG like feFlood, need to convert colors into the operating color space. So add
 10 conversion functions to go between linear and sRGB colors, and use these in feLighting,
 11 and in ImageBuffer (which is only used for non-CG platforms).
 12
 13 Tests: svg/filters/feSpotLight-color.svg
 14
 15 * platform/graphics/ColorUtilities.cpp:
 16 (WebCore::linearToSRGBColorComponent):
 17 (WebCore::sRGBToLinearColorComponent):
 18 (WebCore::linearToSRGBColor):
 19 (WebCore::sRGBToLinearColor):
 20 * platform/graphics/ColorUtilities.h:
 21 * platform/graphics/ImageBuffer.cpp:
 22 (WebCore::ImageBuffer::transformColorSpace):
 23 * platform/graphics/filters/FELighting.cpp:
 24 (WebCore::FELighting::drawLighting):
 25
1262017-12-19 Jer Noble <jer.noble@apple.com>
227
328 Playing media elements which call "pause(); play()" will have the play promise rejected.

Source/WebCore/platform/graphics/ColorUtilities.cpp

2626#include "config.h"
2727#include "ColorUtilities.h"
2828
 29#include "Color.h"
 30#include <wtf/MathExtras.h>
 31
2932namespace WebCore {
3033
3134ColorComponents::ColorComponents(const FloatComponents& floatComponents)

@@ColorComponents::ColorComponents(const FloatComponents& floatComponents)
3639 components[3] = clampedColorComponent(floatComponents.components[3]);
3740}
3841
 42float linearToSRGBColorComponent(float c)
 43{
 44 if (c < 0.0031308)
 45 return 12.92 * c;
 46
 47 return clampTo<float>(1.055 * powf(c, 1.0 / 2.4) - 0.055, 0, 1);
 48}
 49
 50float sRGBToLinearColorComponent(float c)
 51{
 52 if (c <= 0.04045)
 53 return c / 12.92;
 54
 55 return clampTo<float>(powf((c + 0.055) / 1.055, 2.4), 0, 1);
 56}
 57
 58Color linearToSRGBColor(const Color& color)
 59{
 60 float r, g, b, a;
 61 color.getRGBA(r, g, b, a);
 62 r = linearToSRGBColorComponent(r);
 63 g = linearToSRGBColorComponent(g);
 64 b = linearToSRGBColorComponent(b);
 65
 66 return Color(r, g, b, a);
 67}
 68
 69Color sRGBToLinearColor(const Color& color)
 70{
 71 float r, g, b, a;
 72 color.getRGBA(r, g, b, a);
 73 r = sRGBToLinearColorComponent(r);
 74 g = sRGBToLinearColorComponent(g);
 75 b = sRGBToLinearColorComponent(b);
 76
 77 return Color(r, g, b, a);
 78}
 79
3980} // namespace WebCore

Source/WebCore/platform/graphics/ColorUtilities.h

2525
2626#pragma once
2727
 28#include "Color.h"
2829#include <algorithm>
2930#include <math.h>
3031

@@inline unsigned byteOffsetOfPixel(unsigned x, unsigned y, unsigned rowBytes)
147148 return x * bytesPerPixel + y * rowBytes;
148149}
149150
 151// 0-1 components, result is clamped.
 152float linearToSRGBColorComponent(float);
 153float sRGBToLinearColorComponent(float);
 154
 155Color linearToSRGBColor(const Color&);
 156Color sRGBToLinearColor(const Color&);
 157
150158} // namespace WebCore
151159

Source/WebCore/platform/graphics/ImageBuffer.cpp

2828#include "config.h"
2929#include "ImageBuffer.h"
3030
 31#include "ColorUtilities.h"
3132#include "GraphicsContext.h"
3233#include "IntRect.h"
3334#include <wtf/MathExtras.h>

@@void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
135136 std::array<uint8_t, 256> array;
136137 for (unsigned i = 0; i < 256; i++) {
137138 float color = i / 255.0f;
138  color = (color <= 0.04045f ? color / 12.92f : pow((color + 0.055f) / 1.055f, 2.4f));
139  color = std::max(0.0f, color);
140  color = std::min(1.0f, color);
 139 color = sRGBToLinearColorComponent(color);
141140 array[i] = static_cast<uint8_t>(round(color * 255));
142141 }
143142 return array;

@@void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstCo
148147 std::array<uint8_t, 256> array;
149148 for (unsigned i = 0; i < 256; i++) {
150149 float color = i / 255.0f;
151  color = (powf(color, 1.0f / 2.4f) * 1.055f) - 0.055f;
152  color = std::max(0.0f, color);
153  color = std::min(1.0f, color);
 150 color = linearToSRGBColorComponent(color);
154151 array[i] = static_cast<uint8_t>(round(color * 255));
155152 }
156153 return array;

Source/WebCore/platform/graphics/filters/FELighting.cpp

2727#include "config.h"
2828#include "FELighting.h"
2929
 30#include "ColorUtilities.h"
3031#include "FELightingNEON.h"
3132#include <wtf/ParallelJobs.h>
3233

@@bool FELighting::drawLighting(Uint8ClampedArray& pixels, int width, int height)
397398 data.widthMultipliedByPixelSize = width * cPixelSize;
398399 data.widthDecreasedByOne = width - 1;
399400 data.heightDecreasedByOne = height - 1;
400  paintingData.intialLightingData.colorVector = FloatPoint3D(m_lightingColor.red(), m_lightingColor.green(), m_lightingColor.blue());
 401
 402 Color lightColor = (operatingColorSpace() == ColorSpaceLinearRGB) ? sRGBToLinearColor(m_lightingColor) : m_lightingColor;
 403 paintingData.intialLightingData.colorVector = FloatPoint3D(lightColor.red(), lightColor.green(), lightColor.blue());
401404 m_lightSource->initPaintingData(paintingData);
402405
403406 // Top left.

LayoutTests/ChangeLog

 12017-12-30 Simon Fraser <simon.fraser@apple.com>
 2
 3 SVG lighting colors need to be converted into linearSRGB
 4 https://bugs.webkit.org/show_bug.cgi?id=181196
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Compare a far-away green spotlight with a green flood. For some reason (a bug?)
 9 the bottom right pixel always has the wrong color, so mask it out.
 10
 11 * svg/filters/feSpotLight-color-expected.svg: Added.
 12 * svg/filters/feSpotLight-color.svg: Added.
 13
1142017-12-19 Jer Noble <jer.noble@apple.com>
215
316 Playing media elements which call "pause(); play()" will have the play promise rejected.

LayoutTests/svg/filters/feSpotLight-color-expected.svg

 1<svg width="480px" height="600px" xmlns="http://www.w3.org/2000/svg">
 2<defs>
 3 <filter id="filter" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
 4 <feFlood flood-color="rgb(0, 128, 0)"/>
 5 </filter>
 6</defs>
 7<rect x="0" y="00" width="400" height="400" filter="url(#filter)"/>
 8<!-- Mask out a small difference in the bottom right corner -->
 9<rect x="385" y="385" width="20" height="20" fill="black"/>
 10</svg>

LayoutTests/svg/filters/feSpotLight-color.svg

 1<svg width="480px" height="600px" xmlns="http://www.w3.org/2000/svg">
 2<defs>
 3 <filter id="filter" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
 4 <feDiffuseLighting lighting-color="rgb(0, 128, 0)">
 5 <feSpotLight x="200" y="200" z="500000000" />
 6 </feDiffuseLighting>
 7 </filter>
 8</defs>
 9<rect x="0" y="0" width="400" height="400" filter="url(#filter)"/>
 10<!-- Mask out a small difference in the bottom right corner -->
 11<rect x="385" y="385" width="20" height="20" fill="black"/>
 12</svg>