| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // This file implements a simple generic version of the WebKitThemeEngine, | |
| 6 // which is used to draw all the native controls on a web page. We use this | |
| 7 // file when running in layout test mode in order to remove any | |
| 8 // platform-specific rendering differences due to themes, colors, etc. | |
| 9 // | |
| 10 | |
| 11 #include "webkit/tools/test_shell/test_shell_webthemecontrol.h" | |
| 12 | |
| 13 #include "base/logging.h" | |
| 14 #include "skia/ext/platform_canvas.h" | |
| 15 #include "skia/ext/skia_utils_win.h" | |
| 16 #include "third_party/skia/include/core/SkPaint.h" | |
| 17 #include "third_party/skia/include/core/SkPath.h" | |
| 18 | |
| 19 namespace TestShellWebTheme { | |
| 20 | |
| 21 const SkColor kEdgeColor = SK_ColorBLACK; | |
| 22 const SkColor kReadOnlyColor = SkColorSetRGB(0xe9, 0xc2, 0xa6); | |
| 23 const SkColor kFgColor = SK_ColorBLACK; | |
| 24 | |
| 25 const SkColor kBgColors[] = { | |
| 26 SK_ColorBLACK, // Unknown | |
| 27 SkColorSetRGB(0xc9, 0xc9, 0xc9), // Disabled | |
| 28 SkColorSetRGB(0xf3, 0xe0, 0xd0), // Readonly | |
| 29 SkColorSetRGB(0x89, 0xc4, 0xff), // Normal | |
| 30 SkColorSetRGB(0x43, 0xf9, 0xff), // Hot | |
| 31 SkColorSetRGB(0x20, 0xf6, 0xcc), // Focused | |
| 32 SkColorSetRGB(0x00, 0xf3, 0xac), // Hover | |
| 33 SkColorSetRGB(0xa9, 0xff, 0x12), // Pressed | |
| 34 SkColorSetRGB(0xcc, 0xcc, 0xcc) // Indeterminate | |
| 35 }; | |
| 36 | |
| 37 SkIRect Validate(const SkIRect& rect, Control::Type ctype) { | |
| 38 SkIRect retval = rect; | |
| 39 if (ctype == Control::kUncheckedBox_Type || | |
| 40 ctype == Control::kCheckedBox_Type || | |
| 41 ctype == Control::kUncheckedRadio_Type || | |
| 42 ctype == Control::kCheckedRadio_Type) { | |
| 43 // The maximum width and height is 13. Center the square in the passed | |
| 44 // rectangle. | |
| 45 const int kMaxControlSize = 13; | |
| 46 int control_size = std::min(rect.width(), rect.height()); | |
| 47 control_size = std::min(control_size, kMaxControlSize); | |
| 48 | |
| 49 retval.fLeft = rect.fLeft + (rect.width() / 2) - (control_size / 2); | |
| 50 retval.fRight = retval.fLeft + control_size - 1; | |
| 51 retval.fTop = rect.fTop + (rect.height() / 2) - (control_size / 2); | |
| 52 retval.fBottom = retval.fTop + control_size - 1; | |
| 53 } | |
| 54 return retval; | |
| 55 } | |
| 56 | |
| 57 Control::Control(SkCanvas* canvas, const SkIRect& irect, | |
| 58 Type ctype, State cstate) | |
| 59 : canvas_(canvas), | |
| 60 irect_(Validate(irect, ctype)), | |
| 61 type_(ctype), | |
| 62 state_(cstate), | |
| 63 left_(irect_.fLeft), | |
| 64 right_(irect_.fRight), | |
| 65 top_(irect_.fTop), | |
| 66 bottom_(irect_.fBottom), | |
| 67 height_(irect_.height()), | |
| 68 width_(irect_.width()), | |
| 69 edge_color_(kEdgeColor), | |
| 70 bg_color_(kBgColors[cstate]), | |
| 71 fg_color_(kFgColor) { | |
| 72 } | |
| 73 | |
| 74 Control::~Control() { | |
| 75 } | |
| 76 | |
| 77 void Control::box(const SkIRect& rect, SkColor fill_color) { | |
| 78 SkPaint paint; | |
| 79 | |
| 80 paint.setStyle(SkPaint::kFill_Style); | |
| 81 paint.setColor(fill_color); | |
| 82 canvas_->drawIRect(rect, paint); | |
| 83 | |
| 84 paint.setColor(edge_color_); | |
| 85 paint.setStyle(SkPaint::kStroke_Style); | |
| 86 canvas_->drawIRect(rect, paint); | |
| 87 } | |
| 88 | |
| 89 void Control::line(int x0, int y0, int x1, int y1, SkColor color) { | |
| 90 SkPaint paint; | |
| 91 paint.setColor(color); | |
| 92 canvas_->drawLine(SkIntToScalar(x0), SkIntToScalar(y0), | |
| 93 SkIntToScalar(x1), SkIntToScalar(y1), | |
| 94 paint); | |
| 95 } | |
| 96 | |
| 97 void Control::triangle(int x0, int y0, | |
| 98 int x1, int y1, | |
| 99 int x2, int y2, | |
| 100 SkColor color) { | |
| 101 SkPath path; | |
| 102 SkPaint paint; | |
| 103 | |
| 104 paint.setColor(color); | |
| 105 paint.setStyle(SkPaint::kFill_Style); | |
| 106 path.incReserve(4); | |
| 107 path.moveTo(SkIntToScalar(x0), SkIntToScalar(y0)); | |
| 108 path.lineTo(SkIntToScalar(x1), SkIntToScalar(y1)); | |
| 109 path.lineTo(SkIntToScalar(x2), SkIntToScalar(y2)); | |
| 110 path.close(); | |
| 111 canvas_->drawPath(path, paint); | |
| 112 | |
| 113 paint.setColor(edge_color_); | |
| 114 paint.setStyle(SkPaint::kStroke_Style); | |
| 115 canvas_->drawPath(path, paint); | |
| 116 } | |
| 117 | |
| 118 void Control::roundRect(SkColor color) { | |
| 119 SkRect rect; | |
| 120 SkScalar radius = SkIntToScalar(5); | |
| 121 SkPaint paint; | |
| 122 | |
| 123 rect.set(irect_); | |
| 124 paint.setColor(color); | |
| 125 paint.setStyle(SkPaint::kFill_Style); | |
| 126 canvas_->drawRoundRect(rect, radius, radius, paint); | |
| 127 | |
| 128 paint.setColor(edge_color_); | |
| 129 paint.setStyle(SkPaint::kStroke_Style); | |
| 130 canvas_->drawRoundRect(rect, radius, radius, paint); | |
| 131 } | |
| 132 | |
| 133 void Control::oval(SkColor color) { | |
| 134 SkRect rect; | |
| 135 SkPaint paint; | |
| 136 | |
| 137 rect.set(irect_); | |
| 138 paint.setColor(color); | |
| 139 paint.setStyle(SkPaint::kFill_Style); | |
| 140 canvas_->drawOval(rect, paint); | |
| 141 | |
| 142 paint.setColor(edge_color_); | |
| 143 paint.setStyle(SkPaint::kStroke_Style); | |
| 144 canvas_->drawOval(rect, paint); | |
| 145 } | |
| 146 | |
| 147 void Control::circle(SkScalar radius, SkColor color) { | |
| 148 SkScalar cy = SkIntToScalar(top_ + height_ / 2); | |
| 149 SkScalar cx = SkIntToScalar(left_ + width_ / 2); | |
| 150 SkPaint paint; | |
| 151 | |
| 152 paint.setColor(color); | |
| 153 paint.setStyle(SkPaint::kFill_Style); | |
| 154 canvas_->drawCircle(cx, cy, radius, paint); | |
| 155 | |
| 156 paint.setColor(edge_color_); | |
| 157 paint.setStyle(SkPaint::kStroke_Style); | |
| 158 canvas_->drawCircle(cx, cy, radius, paint); | |
| 159 } | |
| 160 | |
| 161 void Control::nested_boxes(int indent_left, int indent_top, | |
| 162 int indent_right, int indent_bottom, | |
| 163 SkColor outer_color, SkColor inner_color) { | |
| 164 SkIRect lirect; | |
| 165 box(irect_, outer_color); | |
| 166 lirect.set(irect_.fLeft + indent_left, irect_.fTop + indent_top, | |
| 167 irect_.fRight - indent_right, irect_.fBottom - indent_bottom); | |
| 168 box(lirect, inner_color); | |
| 169 } | |
| 170 | |
| 171 | |
| 172 void Control::markState() { | |
| 173 // The horizontal lines in a read only control are spaced by this amount. | |
| 174 const int kReadOnlyLineOffset = 5; | |
| 175 | |
| 176 // The length of a triangle side for the corner marks. | |
| 177 const int kTriangleSize = 5; | |
| 178 | |
| 179 switch (state_) { | |
| 180 case kUnknown_State: // FALLTHROUGH | |
| 181 case kDisabled_State: // FALLTHROUGH | |
| 182 case kNormal_State: | |
| 183 // Don't visually mark these states (color is enough). | |
| 184 break; | |
| 185 case kReadOnly_State: | |
| 186 // Drawing lines across the control. | |
| 187 for (int i = top_ + kReadOnlyLineOffset; i < bottom_ ; | |
| 188 i += kReadOnlyLineOffset) { | |
| 189 line(left_ + 1, i, right_ - 1, i, kReadOnlyColor); | |
| 190 } | |
| 191 break; | |
| 192 case kHot_State: | |
| 193 // Draw a triangle in the upper left corner of the control. | |
| 194 triangle(left_, top_, | |
| 195 left_ + kTriangleSize, top_, | |
| 196 left_, top_ + kTriangleSize, edge_color_); | |
| 197 break; | |
| 198 case kHover_State: | |
| 199 // Draw a triangle in the upper right corner of the control. | |
| 200 triangle(right_, top_, | |
| 201 right_, top_ + kTriangleSize, | |
| 202 right_ - kTriangleSize, top_, edge_color_); | |
| 203 break; | |
| 204 case kFocused_State: | |
| 205 // Draw a triangle in the bottom right corner of the control. | |
| 206 triangle(right_, bottom_, | |
| 207 right_ - kTriangleSize, bottom_, | |
| 208 right_, bottom_ - kTriangleSize, edge_color_); | |
| 209 break; | |
| 210 case kPressed_State: | |
| 211 // Draw a triangle in the bottom left corner of the control. | |
| 212 triangle(left_, bottom_, | |
| 213 left_, bottom_ - kTriangleSize, | |
| 214 left_ + kTriangleSize, bottom_, edge_color_); | |
| 215 break; | |
| 216 default: | |
| 217 NOTREACHED(); | |
| 218 break; | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 void Control::draw() { | |
| 223 int half_width = width_ / 2; | |
| 224 int half_height = height_ / 2; | |
| 225 int quarter_width = width_ / 4; | |
| 226 int quarter_height = height_ / 4; | |
| 227 | |
| 228 // Indent amounts for the check in a checkbox or radio button. | |
| 229 const int kCheckIndent = 3; | |
| 230 | |
| 231 // Indent amounts for short and long sides of the scrollbar notches. | |
| 232 const int kNotchLongOffset = 1; | |
| 233 const int kNotchShortOffset = 4; | |
| 234 const int kNoOffset = 0; | |
| 235 int short_offset; | |
| 236 int long_offset; | |
| 237 | |
| 238 // Indent amounts for the short and long sides of a scroll thumb box. | |
| 239 const int kThumbLongIndent = 0; | |
| 240 const int kThumbShortIndent = 2; | |
| 241 | |
| 242 // Indents for the crosshatch on a scroll grip. | |
| 243 const int kGripLongIndent = 3; | |
| 244 const int kGripShortIndent = 5; | |
| 245 | |
| 246 // Indents for the the slider track. | |
| 247 const int kSliderIndent = 2; | |
| 248 | |
| 249 skia::ScopedPlatformPaint scoped_platform_paint(canvas_); | |
| 250 switch (type_) { | |
| 251 case kUnknown_Type: | |
| 252 NOTREACHED(); | |
| 253 break; | |
| 254 case kTextField_Type: | |
| 255 // We render this by hand outside of this function. | |
| 256 NOTREACHED(); | |
| 257 break; | |
| 258 case kPushButton_Type: | |
| 259 // push buttons render as a rounded rectangle | |
| 260 roundRect(bg_color_); | |
| 261 break; | |
| 262 case kUncheckedBox_Type: | |
| 263 // Unchecked boxes are simply plain boxes. | |
| 264 box(irect_, bg_color_); | |
| 265 break; | |
| 266 case kCheckedBox_Type: | |
| 267 nested_boxes(kCheckIndent, kCheckIndent, kCheckIndent, kCheckIndent, | |
| 268 bg_color_, fg_color_); | |
| 269 break; | |
| 270 case kIndeterminateCheckBox_Type: | |
| 271 // Indeterminate checkbox is a box containing '-'. | |
| 272 nested_boxes(kCheckIndent, height_ / 2, kCheckIndent, height_ / 2, | |
| 273 bg_color_, fg_color_); | |
| 274 break; | |
| 275 case kUncheckedRadio_Type: | |
| 276 circle(SkIntToScalar(half_height), bg_color_); | |
| 277 break; | |
| 278 case kCheckedRadio_Type: | |
| 279 circle(SkIntToScalar(half_height), bg_color_); | |
| 280 circle(SkIntToScalar(half_height - kCheckIndent), fg_color_); | |
| 281 break; | |
| 282 case kHorizontalScrollTrackBack_Type: | |
| 283 // Draw a box with a notch at the left. | |
| 284 long_offset = half_height - kNotchLongOffset; | |
| 285 short_offset = width_ - kNotchShortOffset; | |
| 286 nested_boxes(kNoOffset, long_offset, short_offset, long_offset, | |
| 287 bg_color_, edge_color_); | |
| 288 break; | |
| 289 case kHorizontalScrollTrackForward_Type: | |
| 290 // Draw a box with a notch at the right. | |
| 291 long_offset = half_height - kNotchLongOffset; | |
| 292 short_offset = width_ - kNotchShortOffset; | |
| 293 nested_boxes(short_offset, long_offset, kNoOffset, long_offset, | |
| 294 bg_color_, fg_color_); | |
| 295 break; | |
| 296 case kVerticalScrollTrackBack_Type: | |
| 297 // Draw a box with a notch at the top. | |
| 298 long_offset = half_width - kNotchLongOffset; | |
| 299 short_offset = height_ - kNotchShortOffset; | |
| 300 nested_boxes(long_offset, kNoOffset, long_offset, short_offset, | |
| 301 bg_color_, fg_color_); | |
| 302 break; | |
| 303 case kVerticalScrollTrackForward_Type: | |
| 304 // Draw a box with a notch at the bottom. | |
| 305 long_offset = half_width - kNotchLongOffset; | |
| 306 short_offset = height_ - kNotchShortOffset; | |
| 307 nested_boxes(long_offset, short_offset, long_offset, kNoOffset, | |
| 308 bg_color_, fg_color_); | |
| 309 break; | |
| 310 case kHorizontalScrollThumb_Type: | |
| 311 // Draw a narrower box on top of the outside box. | |
| 312 nested_boxes(kThumbLongIndent, kThumbShortIndent, kThumbLongIndent, | |
| 313 kThumbShortIndent, bg_color_, bg_color_); | |
| 314 break; | |
| 315 case kVerticalScrollThumb_Type: | |
| 316 // Draw a shorter box on top of the outside box. | |
| 317 nested_boxes(kThumbShortIndent, kThumbLongIndent, kThumbShortIndent, | |
| 318 kThumbLongIndent, bg_color_, bg_color_); | |
| 319 break; | |
| 320 case kHorizontalSliderThumb_Type: | |
| 321 // Slider thumbs are ovals. | |
| 322 oval(bg_color_); | |
| 323 break; | |
| 324 case kHorizontalScrollGrip_Type: | |
| 325 // Draw a horizontal crosshatch for the grip. | |
| 326 long_offset = half_width - kGripLongIndent; | |
| 327 line(left_ + kGripLongIndent, top_ + half_height, | |
| 328 right_ - kGripLongIndent, top_ + half_height, fg_color_); | |
| 329 line(left_ + long_offset, top_ + kGripShortIndent, | |
| 330 left_ + long_offset, bottom_ - kGripShortIndent, fg_color_); | |
| 331 line(right_ - long_offset, top_ + kGripShortIndent, | |
| 332 right_ - long_offset, bottom_ - kGripShortIndent, fg_color_); | |
| 333 break; | |
| 334 case kVerticalScrollGrip_Type: | |
| 335 // Draw a vertical crosshatch for the grip. | |
| 336 long_offset = half_height - kGripLongIndent; | |
| 337 line(left_ + half_width, top_ + kGripLongIndent, | |
| 338 left_ + half_width, bottom_ - kGripLongIndent, fg_color_); | |
| 339 line(left_ + kGripShortIndent, top_ + long_offset, | |
| 340 right_ - kGripShortIndent, top_ + long_offset, fg_color_); | |
| 341 line(left_ + kGripShortIndent, bottom_ - long_offset, | |
| 342 right_ - kGripShortIndent, bottom_ - long_offset, fg_color_); | |
| 343 break; | |
| 344 case kLeftArrow_Type: | |
| 345 // Draw a left arrow inside a box. | |
| 346 box(irect_, bg_color_); | |
| 347 triangle(right_ - quarter_width, top_ + quarter_height, | |
| 348 right_ - quarter_width, bottom_ - quarter_height, | |
| 349 left_ + quarter_width, top_ + half_height, fg_color_); | |
| 350 break; | |
| 351 case kRightArrow_Type: | |
| 352 // Draw a left arrow inside a box. | |
| 353 box(irect_, bg_color_); | |
| 354 triangle(left_ + quarter_width, top_ + quarter_height, | |
| 355 right_ - quarter_width, top_ + half_height, | |
| 356 left_ + quarter_width, bottom_ - quarter_height, fg_color_); | |
| 357 break; | |
| 358 case kUpArrow_Type: | |
| 359 // Draw an up arrow inside a box. | |
| 360 box(irect_, bg_color_); | |
| 361 triangle(left_ + quarter_width, bottom_ - quarter_height, | |
| 362 left_ + half_width, top_ + quarter_height, | |
| 363 right_ - quarter_width, bottom_ - quarter_height, fg_color_); | |
| 364 break; | |
| 365 case kDownArrow_Type: | |
| 366 // Draw a down arrow inside a box. | |
| 367 box(irect_, bg_color_); | |
| 368 triangle(left_ + quarter_width, top_ + quarter_height, | |
| 369 right_ - quarter_width, top_ + quarter_height, | |
| 370 left_ + half_width, bottom_ - quarter_height, fg_color_); | |
| 371 break; | |
| 372 case kHorizontalSliderTrack_Type: | |
| 373 // Draw a narrow rect for the track plus box hatches on the ends. | |
| 374 SkIRect lirect; | |
| 375 lirect = irect_; | |
| 376 lirect.inset(kNoOffset, half_height - kSliderIndent); | |
| 377 box(lirect, bg_color_); | |
| 378 line(left_, top_, left_, bottom_, edge_color_); | |
| 379 line(right_, top_, right_, bottom_, edge_color_); | |
| 380 break; | |
| 381 case kDropDownButton_Type: | |
| 382 // Draw a box with a big down arrow on top. | |
| 383 box(irect_, bg_color_); | |
| 384 triangle(left_ + quarter_width, top_, | |
| 385 right_ - quarter_width, top_, | |
| 386 left_ + half_width, bottom_, fg_color_); | |
| 387 break; | |
| 388 default: | |
| 389 NOTREACHED(); | |
| 390 break; | |
| 391 } | |
| 392 | |
| 393 markState(); | |
| 394 } | |
| 395 | |
| 396 // Because rendering a text field is dependent on input | |
| 397 // parameters the other controls don't have, we render it directly | |
| 398 // rather than trying to overcomplicate draw() further. | |
| 399 void Control::drawTextField(bool draw_edges, bool fill_content_area, | |
| 400 SkColor color) { | |
| 401 SkPaint paint; | |
| 402 | |
| 403 skia::ScopedPlatformPaint scoped_platform_paint(canvas_); | |
| 404 if (fill_content_area) { | |
| 405 paint.setColor(color); | |
| 406 paint.setStyle(SkPaint::kFill_Style); | |
| 407 canvas_->drawIRect(irect_, paint); | |
| 408 } | |
| 409 if (draw_edges) { | |
| 410 paint.setColor(edge_color_); | |
| 411 paint.setStyle(SkPaint::kStroke_Style); | |
| 412 canvas_->drawIRect(irect_, paint); | |
| 413 } | |
| 414 | |
| 415 markState(); | |
| 416 } | |
| 417 | |
| 418 void | |
| 419 Control::drawProgressBar(const SkIRect& fill_rect) { | |
| 420 SkPaint paint; | |
| 421 | |
| 422 skia::ScopedPlatformPaint scoped_platform_paint(canvas_); | |
| 423 paint.setColor(bg_color_); | |
| 424 paint.setStyle(SkPaint::kFill_Style); | |
| 425 canvas_->drawIRect(irect_, paint); | |
| 426 | |
| 427 // Emulate clipping | |
| 428 SkIRect tofill; | |
| 429 tofill.intersect(irect_, fill_rect); | |
| 430 paint.setColor(fg_color_); | |
| 431 paint.setStyle(SkPaint::kFill_Style); | |
| 432 canvas_->drawIRect(tofill, paint); | |
| 433 | |
| 434 markState(); | |
| 435 } | |
| 436 | |
| 437 } // namespace TestShellWebTheme | |
| 438 | |
| OLD | NEW |