OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Google 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 are | |
6 * met: | |
7 * | |
8 * * Redistributions of source code must retain the above copyright | |
9 * notice, this list of conditions and the following disclaimer. | |
10 * * Redistributions in binary form must reproduce the above | |
11 * copyright notice, this list of conditions and the following disclaimer | |
12 * in the documentation and/or other materials provided with the | |
13 * distribution. | |
14 * * Neither the name of Google Inc. nor the names of its | |
15 * contributors may be used to endorse or promote products derived from | |
16 * this software without specific prior written permission. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
29 */ | |
30 | |
31 #include "config.h" | |
32 #include "core/platform/chromium/PlatformThemeChromiumDefault.h" | |
33 | |
34 namespace WebCore { | |
35 | |
36 unsigned PlatformThemeChromiumDefault::s_thumbInactiveColor = 0xeaeaea; | |
37 unsigned PlatformThemeChromiumDefault::s_thumbActiveColor = 0xf4f4f4; | |
38 unsigned PlatformThemeChromiumDefault::s_trackColor = 0xd3d3d3; | |
39 | |
40 void PlatformThemeChromiumDefault::setScrollbarColors( | |
41 SkColor inactiveColor, SkColor activeColor, SkColor trackColor) | |
42 { | |
43 s_thumbInactiveColor = inactiveColor; | |
44 s_thumbActiveColor = activeColor; | |
45 s_trackColor = trackColor; | |
46 } | |
47 | |
48 static SkScalar clamp(SkScalar value, SkScalar min, SkScalar max) | |
49 { | |
50 return std::min(std::max(value, min), max); | |
51 } | |
52 | |
53 SkColor PlatformThemeChromiumDefault::saturateAndBrighten(const SkScalar hsv[3],
SkScalar saturateAmount, SkScalar brightenAmount) | |
54 { | |
55 SkScalar color[3]; | |
56 color[0] = hsv[0]; | |
57 color[1] = clamp(hsv[1] + saturateAmount, 0.0, 1.0); | |
58 color[2] = clamp(hsv[2] + brightenAmount, 0.0, 1.0); | |
59 return SkHSVToColor(color); | |
60 } | |
61 | |
62 SkColor PlatformThemeChromiumDefault::outlineColor(const SkScalar hsv1[3], const
SkScalar hsv2[3]) | |
63 { | |
64 // GTK Theme engines have way too much control over the layout of | |
65 // the scrollbar. We might be able to more closely approximate its | |
66 // look-and-feel, if we sent whole images instead of just colors | |
67 // from the browser to the renderer. But even then, some themes | |
68 // would just break. | |
69 // | |
70 // So, instead, we don't even try to 100% replicate the look of | |
71 // the native scrollbar. We render our own version, but we make | |
72 // sure to pick colors that blend in nicely with the system GTK | |
73 // theme. In most cases, we can just sample a couple of pixels | |
74 // from the system scrollbar and use those colors to draw our | |
75 // scrollbar. | |
76 // | |
77 // This works fine for the track color and the overall thumb | |
78 // color. But it fails spectacularly for the outline color used | |
79 // around the thumb piece. Not all themes have a clearly defined | |
80 // outline. For some of them it is partially transparent, and for | |
81 // others the thickness is very unpredictable. | |
82 // | |
83 // So, instead of trying to approximate the system theme, we | |
84 // instead try to compute a reasonable looking choice based on the | |
85 // known color of the track and the thumb piece. This is difficult | |
86 // when trying to deal both with high- and low-contrast themes, | |
87 // and both with positive and inverted themes. | |
88 // | |
89 // The following code has been tested to look OK with all of the | |
90 // default GTK themes. | |
91 SkScalar minDiff = clamp((hsv1[1] + hsv2[1]) * 1.2, 0.28, 0.5); | |
92 SkScalar diff = clamp(fabs(hsv1[2] - hsv2[2]) / 2, minDiff, 0.5); | |
93 | |
94 if (hsv1[2] + hsv2[2] > 1.0) | |
95 diff = -diff; | |
96 | |
97 return saturateAndBrighten(hsv2, -0.2, diff); | |
98 } | |
99 | |
100 void PlatformThemeChromiumDefault::paintArrowButton(GraphicsContext* gc, const I
ntRect& rect, ArrowDirection direction, ControlStates states) | |
101 { | |
102 SkCanvas* const canvas = gc->canvas(); | |
103 int widthMiddle, lengthMiddle; | |
104 SkPaint paint; | |
105 if (direction == North || direction == South) { | |
106 widthMiddle = rect.width() / 2 + 1; | |
107 lengthMiddle = rect.height() / 2 + 1; | |
108 } else { | |
109 lengthMiddle = rect.width() / 2 + 1; | |
110 widthMiddle = rect.height() / 2 + 1; | |
111 } | |
112 | |
113 // Calculate button color. | |
114 SkScalar trackHSV[3]; | |
115 SkColorToHSV(trackColor(), trackHSV); | |
116 SkColor buttonColor = saturateAndBrighten(trackHSV, 0, 0.2); | |
117 SkColor backgroundColor = buttonColor; | |
118 if (states & PressedState) { | |
119 SkScalar buttonHSV[3]; | |
120 SkColorToHSV(buttonColor, buttonHSV); | |
121 buttonColor = saturateAndBrighten(buttonHSV, 0, -0.1); | |
122 } else if (states & HoverState) { | |
123 SkScalar buttonHSV[3]; | |
124 SkColorToHSV(buttonColor, buttonHSV); | |
125 buttonColor = saturateAndBrighten(buttonHSV, 0, 0.05); | |
126 } | |
127 | |
128 SkIRect skrect; | |
129 skrect.set(rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.heig
ht()); | |
130 // Paint the background (the area visible behind the rounded corners). | |
131 paint.setColor(backgroundColor); | |
132 canvas->drawIRect(skrect, paint); | |
133 | |
134 // Paint the button's outline and fill the middle | |
135 SkPath outline; | |
136 switch (direction) { | |
137 case North: | |
138 outline.moveTo(rect.x() + 0.5, rect.y() + rect.height() + 0.5); | |
139 outline.rLineTo(0, -(rect.height() - 2)); | |
140 outline.rLineTo(2, -2); | |
141 outline.rLineTo(rect.width() - 5, 0); | |
142 outline.rLineTo(2, 2); | |
143 outline.rLineTo(0, rect.height() - 2); | |
144 break; | |
145 case South: | |
146 outline.moveTo(rect.x() + 0.5, rect.y() - 0.5); | |
147 outline.rLineTo(0, rect.height() - 2); | |
148 outline.rLineTo(2, 2); | |
149 outline.rLineTo(rect.width() - 5, 0); | |
150 outline.rLineTo(2, -2); | |
151 outline.rLineTo(0, -(rect.height() - 2)); | |
152 break; | |
153 case East: | |
154 outline.moveTo(rect.x() - 0.5, rect.y() + 0.5); | |
155 outline.rLineTo(rect.width() - 2, 0); | |
156 outline.rLineTo(2, 2); | |
157 outline.rLineTo(0, rect.height() - 5); | |
158 outline.rLineTo(-2, 2); | |
159 outline.rLineTo(-(rect.width() - 2), 0); | |
160 break; | |
161 case West: | |
162 outline.moveTo(rect.x() + rect.width() + 0.5, rect.y() + 0.5); | |
163 outline.rLineTo(-(rect.width() - 2), 0); | |
164 outline.rLineTo(-2, 2); | |
165 outline.rLineTo(0, rect.height() - 5); | |
166 outline.rLineTo(2, 2); | |
167 outline.rLineTo(rect.width() - 2, 0); | |
168 break; | |
169 } | |
170 outline.close(); | |
171 | |
172 paint.setStyle(SkPaint::kFill_Style); | |
173 paint.setColor(buttonColor); | |
174 canvas->drawPath(outline, paint); | |
175 | |
176 paint.setAntiAlias(true); | |
177 paint.setStyle(SkPaint::kStroke_Style); | |
178 SkScalar thumbHSV[3]; | |
179 SkColorToHSV(thumbInactiveColor(), thumbHSV); | |
180 paint.setColor(outlineColor(trackHSV, thumbHSV)); | |
181 canvas->drawPath(outline, paint); | |
182 | |
183 // If the button is disabled or read-only, the arrow is drawn with the outli
ne color. | |
184 if (states & EnabledState && !(states & ReadOnlyState)) | |
185 paint.setColor(SK_ColorBLACK); | |
186 | |
187 paint.setAntiAlias(false); | |
188 paint.setStyle(SkPaint::kFill_Style); | |
189 | |
190 SkPath path; | |
191 // The constants in this block of code are hand-tailored to produce good | |
192 // looking arrows without anti-aliasing. | |
193 switch (direction) { | |
194 case North: | |
195 path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle + 2); | |
196 path.rLineTo(7, 0); | |
197 path.rLineTo(-4, -4); | |
198 break; | |
199 case South: | |
200 path.moveTo(rect.x() + widthMiddle - 4, rect.y() + lengthMiddle - 3); | |
201 path.rLineTo(7, 0); | |
202 path.rLineTo(-4, 4); | |
203 break; | |
204 case East: | |
205 path.moveTo(rect.x() + lengthMiddle - 3, rect.y() + widthMiddle - 4); | |
206 path.rLineTo(0, 7); | |
207 path.rLineTo(4, -4); | |
208 break; | |
209 case West: | |
210 path.moveTo(rect.x() + lengthMiddle + 1, rect.y() + widthMiddle - 5); | |
211 path.rLineTo(0, 9); | |
212 path.rLineTo(-4, -4); | |
213 break; | |
214 } | |
215 path.close(); | |
216 | |
217 canvas->drawPath(path, paint); | |
218 } | |
219 | |
220 } // namespace WebCore | |
221 | |
OLD | NEW |