1 /* 2 * Copyright (C) 2007 Apple Inc. 3 * Copyright (C) 2007 Alp Toker <alp (at) atoker.com> 4 * Copyright (C) 2008 Collabora Ltd. 5 * Copyright (C) 2008, 2009 Google Inc. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24 #include "config.h" 25 #include "RenderThemeChromiumSkia.h" 26 27 #include "ChromiumBridge.h" 28 #include "CSSValueKeywords.h" 29 #include "GraphicsContext.h" 30 #include "HTMLMediaElement.h" 31 #include "HTMLNames.h" 32 #include "Image.h" 33 #include "MediaControlElements.h" 34 #include "PlatformContextSkia.h" 35 #include "RenderBox.h" 36 #include "RenderMediaControlsChromium.h" 37 #include "RenderObject.h" 38 #include "RenderSlider.h" 39 #include "ScrollbarTheme.h" 40 #include "TimeRanges.h" 41 #include "TransformationMatrix.h" 42 #include "UserAgentStyleSheets.h" 43 44 #include "SkShader.h" 45 #include "SkGradientShader.h" 46 47 namespace WebCore { 48 49 enum PaddingType { 50 TopPadding, 51 RightPadding, 52 BottomPadding, 53 LeftPadding 54 }; 55 56 static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 }; 57 58 // These values all match Safari/Win. 59 static const float defaultControlFontPixelSize = 13; 60 static const float defaultCancelButtonSize = 9; 61 static const float minCancelButtonSize = 5; 62 static const float maxCancelButtonSize = 21; 63 static const float defaultSearchFieldResultsDecorationSize = 13; 64 static const float minSearchFieldResultsDecorationSize = 9; 65 static const float maxSearchFieldResultsDecorationSize = 30; 66 static const float defaultSearchFieldResultsButtonWidth = 18; 67 68 static void setSizeIfAuto(RenderStyle* style, const IntSize& size) 69 { 70 if (style->width().isIntrinsicOrAuto()) 71 style->setWidth(Length(size.width(), Fixed)); 72 if (style->height().isAuto()) 73 style->setHeight(Length(size.height(), Fixed)); 74 } 75 76 static void drawVertLine(SkCanvas* canvas, int x, int y1, int y2, const SkPaint& paint) 77 { 78 SkIRect skrect; 79 skrect.set(x, y1, x + 1, y2 + 1); 80 canvas->drawIRect(skrect, paint); 81 } 82 83 static void drawHorizLine(SkCanvas* canvas, int x1, int x2, int y, const SkPaint& paint) 84 { 85 SkIRect skrect; 86 skrect.set(x1, y, x2 + 1, y + 1); 87 canvas->drawIRect(skrect, paint); 88 } 89 90 static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint) 91 { 92 const int right = rect.x() + rect.width() - 1; 93 const int bottom = rect.y() + rect.height() - 1; 94 drawHorizLine(canvas, rect.x(), right, rect.y(), paint); 95 drawVertLine(canvas, right, rect.y(), bottom, paint); 96 drawHorizLine(canvas, rect.x(), right, bottom, paint); 97 drawVertLine(canvas, rect.x(), rect.y(), bottom, paint); 98 } 99 100 // We aim to match IE here. 101 // -IE uses a font based on the encoding as the default font for form controls. 102 // -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT), 103 // which returns MS Shell Dlg) 104 // -Safari uses Lucida Grande. 105 // 106 // FIXME: The only case where we know we don't match IE is for ANSI encodings. 107 // IE uses MS Shell Dlg there, which we render incorrectly at certain pixel 108 // sizes (e.g. 15px). So, for now we just use Arial. 109 const String& RenderThemeChromiumSkia::defaultGUIFont() 110 { 111 DEFINE_STATIC_LOCAL(String, fontFace, ("Arial")); 112 return fontFace; 113 } 114 115 float RenderThemeChromiumSkia::defaultFontSize = 16.0; 116 117 RenderThemeChromiumSkia::RenderThemeChromiumSkia() 118 { 119 } 120 121 RenderThemeChromiumSkia::~RenderThemeChromiumSkia() 122 { 123 } 124 125 // Use the Windows style sheets to match their metrics. 126 String RenderThemeChromiumSkia::extraDefaultStyleSheet() 127 { 128 return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)); 129 } 130 131 String RenderThemeChromiumSkia::extraQuirksStyleSheet() 132 { 133 return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet)); 134 } 135 136 #if ENABLE(VIDEO) 137 String RenderThemeChromiumSkia::extraMediaControlsStyleSheet() 138 { 139 return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet)); 140 } 141 #endif 142 143 bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const 144 { 145 return true; 146 } 147 148 bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const 149 { 150 // This causes WebKit to draw the focus rings for us. 151 return false; 152 } 153 154 Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const 155 { 156 return Color(0x1e, 0x90, 0xff); 157 } 158 159 Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const 160 { 161 return Color(0xc8, 0xc8, 0xc8); 162 } 163 164 Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const 165 { 166 return Color::black; 167 } 168 169 Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const 170 { 171 return Color(0x32, 0x32, 0x32); 172 } 173 174 Color RenderThemeChromiumSkia::platformFocusRingColor() const 175 { 176 static Color focusRingColor(229, 151, 0, 255); 177 return focusRingColor; 178 } 179 180 double RenderThemeChromiumSkia::caretBlinkInterval() const 181 { 182 // Disable the blinking caret in layout test mode, as it introduces 183 // a race condition for the pixel tests. http://b/1198440 184 if (ChromiumBridge::layoutTestMode()) 185 return 0; 186 187 return caretBlinkIntervalInternal(); 188 } 189 190 void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const 191 { 192 float fontSize = defaultFontSize; 193 194 switch (propId) { 195 case CSSValueWebkitMiniControl: 196 case CSSValueWebkitSmallControl: 197 case CSSValueWebkitControl: 198 // Why 2 points smaller? Because that's what Gecko does. Note that we 199 // are assuming a 96dpi screen, which is the default that we use on 200 // Windows. 201 static const float pointsPerInch = 72.0f; 202 static const float pixelsPerInch = 96.0f; 203 fontSize -= (2.0f / pointsPerInch) * pixelsPerInch; 204 break; 205 } 206 207 fontDescription.firstFamily().setFamily(defaultGUIFont()); 208 fontDescription.setSpecifiedSize(fontSize); 209 fontDescription.setIsAbsoluteSize(true); 210 fontDescription.setGenericFamily(FontDescription::NoFamily); 211 fontDescription.setWeight(FontWeightNormal); 212 fontDescription.setItalic(false); 213 } 214 215 int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const 216 { 217 return 0; 218 } 219 220 // These are the default dimensions of radio buttons and checkboxes. 221 static const int widgetStandardWidth = 13; 222 static const int widgetStandardHeight = 13; 223 224 // Return a rectangle that has the same center point as |original|, but with a 225 // size capped at |width| by |height|. 226 IntRect center(const IntRect& original, int width, int height) 227 { 228 width = std::min(original.width(), width); 229 height = std::min(original.height(), height); 230 int x = original.x() + (original.width() - width) / 2; 231 int y = original.y() + (original.height() - height) / 2; 232 233 return IntRect(x, y, width, height); 234 } 235 236 bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 237 { 238 static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef(); 239 static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef(); 240 static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOn").releaseRef(); 241 static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOff").releaseRef(); 242 243 Image* image; 244 245 if (this->isEnabled(o)) 246 image = this->isChecked(o) ? checkedImage : uncheckedImage; 247 else 248 image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage; 249 250 i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth)); 251 return false; 252 } 253 254 void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const 255 { 256 // If the width and height are both specified, then we have nothing to do. 257 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 258 return; 259 260 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary 261 // for now. It matches Firefox. At different DPI settings on Windows, 262 // querying the theme gives you a larger size that accounts for the higher 263 // DPI. Until our entire engine honors a DPI setting other than 96, we 264 // can't rely on the theme's metrics. 265 const IntSize size(widgetStandardHeight, widgetStandardWidth); 266 setSizeIfAuto(style, size); 267 } 268 269 bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 270 { 271 static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef(); 272 static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef(); 273 static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxRadioDisabledOn").releaseRef(); 274 static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxRadioDisabledOff").releaseRef(); 275 276 Image* image; 277 if (this->isEnabled(o)) 278 image = this->isChecked(o) ? checkedImage : uncheckedImage; 279 else 280 image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage; 281 282 i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth)); 283 return false; 284 } 285 286 void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const 287 { 288 // Use same sizing for radio box as checkbox. 289 setCheckboxSize(style); 290 } 291 292 static SkColor brightenColor(double h, double s, double l, float brightenAmount) 293 { 294 l += brightenAmount; 295 if (l > 1.0) 296 l = 1.0; 297 if (l < 0.0) 298 l = 0.0; 299 300 return makeRGBAFromHSLA(h, s, l, 1.0); 301 } 302 303 static void paintButtonLike(RenderTheme* theme, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 304 { 305 SkCanvas* const canvas = i.context->platformContext()->canvas(); 306 SkPaint paint; 307 SkRect skrect; 308 const int right = rect.x() + rect.width(); 309 const int bottom = rect.y() + rect.height(); 310 SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd); 311 if (o->style()->hasBackground()) 312 baseColor = o->style()->backgroundColor().rgb(); 313 double h, s, l; 314 Color(baseColor).getHSL(h, s, l); 315 // Our standard gradient is from 0xdd to 0xf8. This is the amount of 316 // increased luminance between those values. 317 SkColor lightColor(brightenColor(h, s, l, 0.105)); 318 319 // If the button is too small, fallback to drawing a single, solid color 320 if (rect.width() < 5 || rect.height() < 5) { 321 paint.setColor(baseColor); 322 skrect.set(rect.x(), rect.y(), right, bottom); 323 canvas->drawRect(skrect, paint); 324 return; 325 } 326 327 const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55; 328 paint.setARGB(borderAlpha, 0, 0, 0); 329 canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint); 330 canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint); 331 canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint); 332 canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint); 333 334 paint.setColor(SK_ColorBLACK); 335 SkPoint p[2]; 336 const int lightEnd = theme->isPressed(o) ? 1 : 0; 337 const int darkEnd = !lightEnd; 338 p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y())); 339 p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1)); 340 SkColor colors[2]; 341 colors[0] = lightColor; 342 colors[1] = baseColor; 343 344 SkShader* shader = SkGradientShader::CreateLinear( 345 p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL); 346 paint.setStyle(SkPaint::kFill_Style); 347 paint.setShader(shader); 348 shader->unref(); 349 350 skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1); 351 canvas->drawRect(skrect, paint); 352 353 paint.setShader(NULL); 354 paint.setColor(brightenColor(h, s, l, -0.0588)); 355 canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint); 356 canvas->drawPoint(right - 2, rect.y() + 1, paint); 357 canvas->drawPoint(rect.x() + 1, bottom - 2, paint); 358 canvas->drawPoint(right - 2, bottom - 2, paint); 359 } 360 361 bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 362 { 363 paintButtonLike(this, o, i, rect); 364 return false; 365 } 366 367 void RenderThemeChromiumSkia::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 368 { 369 if (style->appearance() == PushButtonPart) { 370 // Ignore line-height. 371 style->setLineHeight(RenderStyle::initialLineHeight()); 372 } 373 } 374 375 376 bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 377 { 378 return true; 379 } 380 381 bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) 382 { 383 return paintTextField(o, i, r); 384 } 385 386 void RenderThemeChromiumSkia::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 387 { 388 // Ignore line-height. 389 style->setLineHeight(RenderStyle::initialLineHeight()); 390 } 391 392 bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) 393 { 394 return paintTextField(o, i, r); 395 } 396 397 void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 398 { 399 // Scale the button size based on the font size 400 float fontScale = style->fontSize() / defaultControlFontPixelSize; 401 int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize)); 402 style->setWidth(Length(cancelButtonSize, Fixed)); 403 style->setHeight(Length(cancelButtonSize, Fixed)); 404 } 405 406 bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) 407 { 408 IntRect bounds = r; 409 ASSERT(o->parent()); 410 if (!o->parent() || !o->parent()->isBox()) 411 return false; 412 413 RenderBox* parentRenderBox = toRenderBox(o->parent()); 414 415 IntRect parentBox = parentRenderBox->absoluteContentBox(); 416 417 // Make sure the scaled button stays square and will fit in its parent's box 418 bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height()))); 419 bounds.setWidth(bounds.height()); 420 421 // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will 422 // be one pixel closer to the bottom of the field. This tends to look better with the text. 423 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 424 425 static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef(); 426 static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef(); 427 i.context->drawImage(isPressed(o) ? cancelPressedImage : cancelImage, o->style()->colorSpace(), bounds); 428 return false; 429 } 430 431 void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 432 { 433 IntSize emptySize(1, 11); 434 style->setWidth(Length(emptySize.width(), Fixed)); 435 style->setHeight(Length(emptySize.height(), Fixed)); 436 } 437 438 void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 439 { 440 // Scale the decoration size based on the font size 441 float fontScale = style->fontSize() / defaultControlFontPixelSize; 442 int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), 443 maxSearchFieldResultsDecorationSize)); 444 style->setWidth(Length(magnifierSize, Fixed)); 445 style->setHeight(Length(magnifierSize, Fixed)); 446 } 447 448 bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) 449 { 450 IntRect bounds = r; 451 ASSERT(o->parent()); 452 if (!o->parent() || !o->parent()->isBox()) 453 return false; 454 455 RenderBox* parentRenderBox = toRenderBox(o->parent()); 456 IntRect parentBox = parentRenderBox->absoluteContentBox(); 457 458 // Make sure the scaled decoration stays square and will fit in its parent's box 459 bounds.setHeight(std::min(parentBox.width(), std::min(parentBox.height(), bounds.height()))); 460 bounds.setWidth(bounds.height()); 461 462 // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will 463 // be one pixel closer to the bottom of the field. This tends to look better with the text. 464 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 465 466 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef(); 467 i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); 468 return false; 469 } 470 471 void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const 472 { 473 // Scale the button size based on the font size 474 float fontScale = style->fontSize() / defaultControlFontPixelSize; 475 int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale), 476 maxSearchFieldResultsDecorationSize)); 477 int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize); 478 style->setWidth(Length(magnifierWidth, Fixed)); 479 style->setHeight(Length(magnifierHeight, Fixed)); 480 } 481 482 bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) 483 { 484 IntRect bounds = r; 485 ASSERT(o->parent()); 486 if (!o->parent()) 487 return false; 488 if (!o->parent() || !o->parent()->isBox()) 489 return false; 490 491 RenderBox* parentRenderBox = toRenderBox(o->parent()); 492 IntRect parentBox = parentRenderBox->absoluteContentBox(); 493 494 // Make sure the scaled decoration will fit in its parent's box 495 bounds.setHeight(std::min(parentBox.height(), bounds.height())); 496 bounds.setWidth(std::min(parentBox.width(), static_cast<int>(bounds.height() * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize))); 497 498 // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will 499 // be one pixel closer to the bottom of the field. This tends to look better with the text. 500 bounds.setY(parentBox.y() + (parentBox.height() - bounds.height() + 1) / 2); 501 502 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef(); 503 i.context->drawImage(magnifierImage, o->style()->colorSpace(), bounds); 504 return false; 505 } 506 507 bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 508 { 509 #if ENABLE(VIDEO) 510 return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect); 511 #else 512 UNUSED_PARAM(object); 513 UNUSED_PARAM(paintInfo); 514 UNUSED_PARAM(rect); 515 return false; 516 #endif 517 } 518 519 bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 520 { 521 #if ENABLE(VIDEO) 522 return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect); 523 #else 524 UNUSED_PARAM(object); 525 UNUSED_PARAM(paintInfo); 526 UNUSED_PARAM(rect); 527 return false; 528 #endif 529 } 530 531 bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 532 { 533 #if ENABLE(VIDEO) 534 return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect); 535 #else 536 UNUSED_PARAM(object); 537 UNUSED_PARAM(paintInfo); 538 UNUSED_PARAM(rect); 539 return false; 540 #endif 541 } 542 543 void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const 544 { 545 #if ENABLE(VIDEO) 546 RenderMediaControlsChromium::adjustMediaSliderThumbSize(object); 547 #else 548 UNUSED_PARAM(object); 549 #endif 550 } 551 552 bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 553 { 554 #if ENABLE(VIDEO) 555 return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect); 556 #else 557 UNUSED_PARAM(object); 558 UNUSED_PARAM(paintInfo); 559 UNUSED_PARAM(rect); 560 return false; 561 #endif 562 } 563 564 bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 565 { 566 #if ENABLE(VIDEO) 567 return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect); 568 #else 569 UNUSED_PARAM(object); 570 UNUSED_PARAM(paintInfo); 571 UNUSED_PARAM(rect); 572 return false; 573 #endif 574 } 575 576 bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 577 { 578 #if ENABLE(VIDEO) 579 return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect); 580 #else 581 UNUSED_PARAM(object); 582 UNUSED_PARAM(paintInfo); 583 UNUSED_PARAM(rect); 584 return false; 585 #endif 586 } 587 588 bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const RenderObject::PaintInfo& paintInfo, const IntRect& rect) 589 { 590 #if ENABLE(VIDEO) 591 return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect); 592 #else 593 UNUSED_PARAM(object); 594 UNUSED_PARAM(paintInfo); 595 UNUSED_PARAM(rect); 596 return false; 597 #endif 598 } 599 600 void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const 601 { 602 // Height is locked to auto on all browsers. 603 style->setLineHeight(RenderStyle::initialLineHeight()); 604 } 605 606 bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 607 { 608 SkCanvas* const canvas = i.context->platformContext()->canvas(); 609 const int right = rect.x() + rect.width(); 610 const int middle = rect.y() + rect.height() / 2; 611 612 paintButtonLike(this, o, i, rect); 613 614 SkPaint paint; 615 paint.setColor(SK_ColorBLACK); 616 paint.setAntiAlias(true); 617 paint.setStyle(SkPaint::kFill_Style); 618 619 int arrowXPosition = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13; 620 SkPath path; 621 path.moveTo(arrowXPosition, middle - 3); 622 path.rLineTo(6, 0); 623 path.rLineTo(-3, 6); 624 path.close(); 625 canvas->drawPath(path, paint); 626 627 return false; 628 } 629 630 void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const 631 { 632 adjustMenuListStyle(selector, style, e); 633 } 634 635 // Used to paint styled menulists (i.e. with a non-default border) 636 bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 637 { 638 return paintMenuList(o, i, rect); 639 } 640 641 bool RenderThemeChromiumSkia::paintSliderTrack(RenderObject*, const RenderObject::PaintInfo& i, const IntRect& rect) 642 { 643 // Just paint a grey box for now (matches the color of a scrollbar background. 644 SkCanvas* const canvas = i.context->platformContext()->canvas(); 645 int verticalCenter = rect.y() + rect.height() / 2; 646 int top = std::max(rect.y(), verticalCenter - 2); 647 int bottom = std::min(rect.y() + rect.height(), verticalCenter + 2); 648 649 SkPaint paint; 650 const SkColor grey = SkColorSetARGB(0xff, 0xe3, 0xdd, 0xd8); 651 paint.setColor(grey); 652 653 SkRect skrect; 654 skrect.set(rect.x(), top, rect.x() + rect.width(), bottom); 655 canvas->drawRect(skrect, paint); 656 657 return false; 658 } 659 660 bool RenderThemeChromiumSkia::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) 661 { 662 // Make a thumb similar to the scrollbar thumb. 663 const bool hovered = isHovered(o) || toRenderSlider(o->parent())->inDragMode(); 664 const int midx = rect.x() + rect.width() / 2; 665 const int midy = rect.y() + rect.height() / 2; 666 const bool vertical = (o->style()->appearance() == SliderThumbVerticalPart); 667 SkCanvas* const canvas = i.context->platformContext()->canvas(); 668 669 const SkColor thumbLightGrey = SkColorSetARGB(0xff, 0xf4, 0xf2, 0xef); 670 const SkColor thumbDarkGrey = SkColorSetARGB(0xff, 0xea, 0xe5, 0xe0); 671 SkPaint paint; 672 paint.setColor(hovered ? SK_ColorWHITE : thumbLightGrey); 673 674 SkIRect skrect; 675 if (vertical) 676 skrect.set(rect.x(), rect.y(), midx + 1, rect.bottom()); 677 else 678 skrect.set(rect.x(), rect.y(), rect.right(), midy + 1); 679 680 canvas->drawIRect(skrect, paint); 681 682 paint.setColor(hovered ? thumbLightGrey : thumbDarkGrey); 683 684 if (vertical) 685 skrect.set(midx + 1, rect.y(), rect.right(), rect.bottom()); 686 else 687 skrect.set(rect.x(), midy + 1, rect.right(), rect.bottom()); 688 689 canvas->drawIRect(skrect, paint); 690 691 const SkColor borderDarkGrey = SkColorSetARGB(0xff, 0x9d, 0x96, 0x8e); 692 paint.setColor(borderDarkGrey); 693 drawBox(canvas, rect, paint); 694 695 if (rect.height() > 10 && rect.width() > 10) { 696 drawHorizLine(canvas, midx - 2, midx + 2, midy, paint); 697 drawHorizLine(canvas, midx - 2, midx + 2, midy - 3, paint); 698 drawHorizLine(canvas, midx - 2, midx + 2, midy + 3, paint); 699 } 700 701 return false; 702 } 703 704 int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const 705 { 706 return menuListInternalPadding(style, LeftPadding); 707 } 708 709 int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const 710 { 711 return menuListInternalPadding(style, RightPadding); 712 } 713 714 int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const 715 { 716 return menuListInternalPadding(style, TopPadding); 717 } 718 719 int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const 720 { 721 return menuListInternalPadding(style, BottomPadding); 722 } 723 724 int RenderThemeChromiumSkia::buttonInternalPaddingLeft() const 725 { 726 return 3; 727 } 728 729 int RenderThemeChromiumSkia::buttonInternalPaddingRight() const 730 { 731 return 3; 732 } 733 734 int RenderThemeChromiumSkia::buttonInternalPaddingTop() const 735 { 736 return 1; 737 } 738 739 int RenderThemeChromiumSkia::buttonInternalPaddingBottom() const 740 { 741 return 1; 742 } 743 744 #if ENABLE(VIDEO) 745 bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e) 746 { 747 return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e); 748 } 749 #endif 750 751 // static 752 void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize) 753 { 754 defaultFontSize = static_cast<float>(fontSize); 755 } 756 757 double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const 758 { 759 return RenderTheme::caretBlinkInterval(); 760 } 761 762 int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const 763 { 764 // This internal padding is in addition to the user-supplied padding. 765 // Matches the FF behavior. 766 int padding = styledMenuListInternalPadding[paddingType]; 767 768 // Reserve the space for right arrow here. The rest of the padding is 769 // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from 770 // RenderMenuList to lay out the individual items in the popup. 771 // If the MenuList actually has appearance "NoAppearance", then that means 772 // we don't draw a button, so don't reserve space for it. 773 const int barType = style->direction() == LTR ? RightPadding : LeftPadding; 774 if (paddingType == barType && style->appearance() != NoControlPart) 775 padding += ScrollbarTheme::nativeTheme()->scrollbarThickness(); 776 777 return padding; 778 } 779 780 } // namespace WebCore 781