Home | History | Annotate | Download | only in rendering
      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