835dea046791c4b12857ce6869c102b70156a03e
[WebKit-https.git] / Source / WebCore / platform / graphics / ImageBuffer.cpp
1 /*
2  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
3  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "ImageBuffer.h"
29
30 #include "GraphicsContext.h"
31 #include "IntRect.h"
32 #include <wtf/MathExtras.h>
33
34 namespace WebCore {
35
36 static const float MaxClampedLength = 4096;
37 static const float MaxClampedArea = MaxClampedLength * MaxClampedLength;
38
39 bool ImageBuffer::sizeNeedsClamping(const FloatSize& size)
40 {
41     if (size.isEmpty())
42         return false;
43
44     return floorf(size.height()) * floorf(size.width()) > MaxClampedArea;
45 }
46
47 bool ImageBuffer::sizeNeedsClamping(const FloatSize& size, FloatSize& scale)
48 {
49     FloatSize scaledSize(size);
50     scaledSize.scale(scale.width(), scale.height());
51
52     if (!sizeNeedsClamping(scaledSize))
53         return false;
54
55     // The area of scaled size is bigger than the upper limit, adjust the scale to fit.
56     scale.scale(sqrtf(MaxClampedArea / (scaledSize.width() * scaledSize.height())));
57     ASSERT(!sizeNeedsClamping(size, scale));
58     return true;
59 }
60
61 FloatSize ImageBuffer::clampedSize(const FloatSize& size)
62 {
63     return size.shrunkTo(FloatSize(MaxClampedLength, MaxClampedLength));
64 }
65
66 FloatSize ImageBuffer::clampedSize(const FloatSize& size, FloatSize& scale)
67 {
68     if (size.isEmpty())
69         return size;
70
71     FloatSize clampedSize = ImageBuffer::clampedSize(size);
72     scale = FloatSize(clampedSize.width() / size.width(), clampedSize.height() / size.height());
73     ASSERT(!sizeNeedsClamping(clampedSize));
74     ASSERT(!sizeNeedsClamping(size, scale));
75     return clampedSize;
76 }
77
78 FloatRect ImageBuffer::clampedRect(const FloatRect& rect)
79 {
80     return FloatRect(rect.location(), clampedSize(rect.size()));
81 }
82
83 #if !USE(CG)
84 FloatSize ImageBuffer::sizeForDestinationSize(FloatSize size) const
85 {
86     return size;
87 }
88
89 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
90 {
91     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<int>, deviceRgbLUT, ());
92     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<int>, linearRgbLUT, ());
93
94     if (srcColorSpace == dstColorSpace)
95         return;
96
97     // only sRGB <-> linearRGB are supported at the moment
98     if ((srcColorSpace != ColorSpaceLinearRGB && srcColorSpace != ColorSpaceDeviceRGB)
99         || (dstColorSpace != ColorSpaceLinearRGB && dstColorSpace != ColorSpaceDeviceRGB))
100         return;
101
102     if (dstColorSpace == ColorSpaceLinearRGB) {
103         if (linearRgbLUT.isEmpty()) {
104             for (unsigned i = 0; i < 256; i++) {
105                 float color = i  / 255.0f;
106                 color = (color <= 0.04045f ? color / 12.92f : pow((color + 0.055f) / 1.055f, 2.4f));
107                 color = std::max(0.0f, color);
108                 color = std::min(1.0f, color);
109                 linearRgbLUT.append(static_cast<int>(round(color * 255)));
110             }
111         }
112         platformTransformColorSpace(linearRgbLUT);
113     } else if (dstColorSpace == ColorSpaceDeviceRGB) {
114         if (deviceRgbLUT.isEmpty()) {
115             for (unsigned i = 0; i < 256; i++) {
116                 float color = i / 255.0f;
117                 color = (powf(color, 1.0f / 2.4f) * 1.055f) - 0.055f;
118                 color = std::max(0.0f, color);
119                 color = std::min(1.0f, color);
120                 deviceRgbLUT.append(static_cast<int>(round(color * 255)));
121             }
122         }
123         platformTransformColorSpace(deviceRgbLUT);
124     }
125 }
126 #endif // USE(CG)
127
128 inline void ImageBuffer::genericConvertToLuminanceMask()
129 {
130     IntRect luminanceRect(IntPoint(), internalSize());
131     RefPtr<Uint8ClampedArray> srcPixelArray = getUnmultipliedImageData(luminanceRect);
132     
133     unsigned pixelArrayLength = srcPixelArray->length();
134     for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
135         unsigned char a = srcPixelArray->item(pixelOffset + 3);
136         if (!a)
137             continue;
138         unsigned char r = srcPixelArray->item(pixelOffset);
139         unsigned char g = srcPixelArray->item(pixelOffset + 1);
140         unsigned char b = srcPixelArray->item(pixelOffset + 2);
141         
142         double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
143         srcPixelArray->set(pixelOffset + 3, luma);
144     }
145     putByteArray(Unmultiplied, srcPixelArray.get(), luminanceRect.size(), luminanceRect, IntPoint());
146 }
147
148 void ImageBuffer::convertToLuminanceMask()
149 {
150     // Add platform specific functions with platformConvertToLuminanceMask here later.
151     genericConvertToLuminanceMask();
152 }
153
154 #if !USE(CAIRO)
155 PlatformLayer* ImageBuffer::platformLayer() const
156 {
157     return 0;
158 }
159
160 bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D&, GC3Denum, Platform3DObject, GC3Denum, bool, bool)
161 {
162     return false;
163 }
164 #endif
165
166 std::unique_ptr<ImageBuffer> ImageBuffer::createCompatibleBuffer(const FloatSize& size, float resolutionScale, ColorSpace colorSpace, const GraphicsContext& context, bool)
167 {
168     return create(size, context.renderingMode(), resolutionScale, colorSpace);
169 }
170
171 }