| 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 |