Support "plus-lighter" in mix-blend mode
[WebKit-https.git] / Source / WebCore / platform / graphics / GraphicsTypes.cpp
1 /*
2  * Copyright (C) 2006 Apple Inc.  All rights reserved.
3  * Copyright (C) 2012 Rik Cabanier (cabanier@adobe.com)
4  * Copyright (C) 2014 Adobe Systems Incorporated. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
26  */
27
28 #include "config.h"
29 #include "GraphicsTypes.h"
30
31 #include <wtf/Assertions.h>
32 #include <wtf/text/WTFString.h>
33
34 namespace WebCore {
35
36 static const char* const compositeOperatorNames[] = {
37     "clear",
38     "copy",
39     "source-over",
40     "source-in",
41     "source-out",
42     "source-atop",
43     "destination-over",
44     "destination-in",
45     "destination-out",
46     "destination-atop",
47     "xor",
48     "darker",
49     "lighter"
50 };
51
52 static const char* const blendOperatorNames[] = {
53     "normal",
54     "multiply",
55     "screen",
56     "darken",
57     "lighten",
58     "overlay",
59     "color-dodge",
60     "color-burn",
61     "hard-light",
62     "soft-light",
63     "difference",
64     "exclusion",
65     "hue",
66     "saturation",
67     "color",
68     "luminosity",
69     "plus-darker",
70     "plus-lighter"
71 };
72 const int numCompositeOperatorNames = WTF_ARRAY_LENGTH(compositeOperatorNames);
73 const int numBlendOperatorNames = WTF_ARRAY_LENGTH(blendOperatorNames);
74
75 bool parseBlendMode(const String& s, BlendMode& blendMode)
76 {
77     for (int i = 0; i < numBlendOperatorNames; i++) {
78         if (s == blendOperatorNames[i]) {
79             blendMode = static_cast<BlendMode>(i+1);
80             return true;
81         }
82     }
83     
84     return false;
85 }
86
87 bool parseCompositeAndBlendOperator(const String& s, CompositeOperator& op, BlendMode& blendOp)
88 {
89     for (int i = 0; i < numCompositeOperatorNames; i++) {
90         if (s == compositeOperatorNames[i]) {
91             op = static_cast<CompositeOperator>(i);
92             blendOp = BlendModeNormal;
93             return true;
94         }
95     }
96     
97     if (parseBlendMode(s, blendOp)) {
98         // For now, blending will always assume source-over. This will be fixed in the future
99         op = CompositeSourceOver;
100         return true;
101     }
102     
103     return false;
104 }
105
106 // FIXME: when we support blend modes in combination with compositing other than source-over
107 // this routine needs to be updated.
108 String compositeOperatorName(CompositeOperator op, BlendMode blendOp)
109 {
110     ASSERT(op >= 0);
111     ASSERT(op < numCompositeOperatorNames);
112     ASSERT(blendOp >= 0);
113     ASSERT(blendOp <= numBlendOperatorNames);
114     if (blendOp != BlendModeNormal)
115         return blendOperatorNames[blendOp-1];
116     return compositeOperatorNames[op];
117 }
118
119 bool parseLineCap(const String& s, LineCap& cap)
120 {
121     if (s == "butt") {
122         cap = ButtCap;
123         return true;
124     }
125     if (s == "round") {
126         cap = RoundCap;
127         return true;
128     }
129     if (s == "square") {
130         cap = SquareCap;
131         return true;
132     }
133     return false;
134 }
135
136 String lineCapName(LineCap cap)
137 {
138     ASSERT(cap >= 0);
139     ASSERT(cap < 3);
140     const char* const names[3] = { "butt", "round", "square" };
141     return names[cap];
142 }
143
144 bool parseLineJoin(const String& s, LineJoin& join)
145 {
146     if (s == "miter") {
147         join = MiterJoin;
148         return true;
149     }
150     if (s == "round") {
151         join = RoundJoin;
152         return true;
153     }
154     if (s == "bevel") {
155         join = BevelJoin;
156         return true;
157     }
158     return false;
159 }
160
161 String lineJoinName(LineJoin join)
162 {
163     ASSERT(join >= 0);
164     ASSERT(join < 3);
165     const char* const names[3] = { "miter", "round", "bevel" };
166     return names[join];
167 }
168
169 String textAlignName(TextAlign align)
170 {
171     ASSERT(align >= 0);
172     ASSERT(align < 5);
173     const char* const names[5] = { "start", "end", "left", "center", "right" };
174     return names[align];
175 }
176
177 bool parseTextAlign(const String& s, TextAlign& align)
178 {
179     if (s == "start") {
180         align = StartTextAlign;
181         return true;
182     }
183     if (s == "end") {
184         align = EndTextAlign;
185         return true;
186     }
187     if (s == "left") {
188         align = LeftTextAlign;
189         return true;
190     }
191     if (s == "center") {
192         align = CenterTextAlign;
193         return true;
194     }
195     if (s == "right") {
196         align = RightTextAlign;
197         return true;
198     }
199     return false;
200 }
201
202 String textBaselineName(TextBaseline baseline)
203 {
204     ASSERT(baseline >= 0);
205     ASSERT(baseline < 6);
206     const char* const names[6] = { "alphabetic", "top", "middle", "bottom", "ideographic", "hanging" };
207     return names[baseline];
208 }
209
210 bool parseTextBaseline(const String& s, TextBaseline& baseline)
211 {
212     if (s == "alphabetic") {
213         baseline = AlphabeticTextBaseline;
214         return true;
215     }
216     if (s == "top") {
217         baseline = TopTextBaseline;
218         return true;
219     }
220     if (s == "middle") {
221         baseline = MiddleTextBaseline;
222         return true;
223     }
224     if (s == "bottom") {
225         baseline = BottomTextBaseline;
226         return true;
227     }
228     if (s == "ideographic") {
229         baseline = IdeographicTextBaseline;
230         return true;
231     }
232     if (s == "hanging") {
233         baseline = HangingTextBaseline;
234         return true;
235     }
236     return false;
237 }
238
239 }