Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2007, 2008, 2009 Apple Inc.
      3  * Copyright (C) 2009 Kenneth Rohde Christiansen
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  *
     20  */
     21 
     22 #include "config.h"
     23 #include "RenderThemeSafari.h"
     24 #include "RenderThemeWin.h"
     25 #include "Settings.h"
     26 
     27 #if USE(SAFARI_THEME)
     28 
     29 #include "CSSValueKeywords.h"
     30 #include "Document.h"
     31 #include "Element.h"
     32 #include "Frame.h"
     33 #include "FrameView.h"
     34 #include "GraphicsContext.h"
     35 #include "HTMLInputElement.h"
     36 #include "HTMLMediaElement.h"
     37 #include "HTMLNames.h"
     38 #include "RenderMediaControls.h"
     39 #include "RenderSlider.h"
     40 #include "RenderView.h"
     41 #include "RetainPtr.h"
     42 #include "SoftLinking.h"
     43 #include "cssstyleselector.h"
     44 #include <CoreGraphics/CoreGraphics.h>
     45 
     46 using std::min;
     47 
     48 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeMac.
     49 
     50 namespace WebCore {
     51 
     52 using namespace HTMLNames;
     53 using namespace SafariTheme;
     54 
     55 enum {
     56     topMargin,
     57     rightMargin,
     58     bottomMargin,
     59     leftMargin
     60 };
     61 
     62 enum {
     63     topPadding,
     64     rightPadding,
     65     bottomPadding,
     66     leftPadding
     67 };
     68 
     69 PassRefPtr<RenderTheme> RenderThemeSafari::create()
     70 {
     71     return adoptRef(new RenderThemeSafari);
     72 }
     73 
     74 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
     75 {
     76     static RenderTheme* safariTheme = RenderThemeSafari::create().releaseRef();
     77     static RenderTheme* windowsTheme = RenderThemeWin::create().releaseRef();
     78 
     79     // FIXME: This is called before Settings has been initialized by WebKit, so will return a
     80     // potentially wrong answer the very first time it's called (see
     81     // <https://bugs.webkit.org/show_bug.cgi?id=26493>).
     82     if (Settings::shouldPaintNativeControls()) {
     83         RenderTheme::setCustomFocusRingColor(safariTheme->platformFocusRingColor());
     84         return windowsTheme; // keep the reference of one.
     85     }
     86     return safariTheme; // keep the reference of one.
     87 }
     88 
     89 #ifdef DEBUG_ALL
     90 SOFT_LINK_DEBUG_LIBRARY(SafariTheme)
     91 #else
     92 SOFT_LINK_LIBRARY(SafariTheme)
     93 #endif
     94 
     95 SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state), (part, context, rect, size, state))
     96 #if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2
     97 SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value))
     98 #endif
     99 SOFT_LINK_OPTIONAL(SafariTheme, STCopyThemeColor, CGColorRef, APIENTRY, (unsigned color, SafariTheme::ThemeControlState));
    100 
    101 static const unsigned stFocusRingColorID = 4;
    102 
    103 static const unsigned aquaFocusRingColor = 0xFF7DADD9;
    104 
    105 static RGBA32 makeRGBAFromCGColor(CGColorRef color)
    106 {
    107     const CGFloat* components = CGColorGetComponents(color);
    108     return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]);
    109 }
    110 
    111 ThemeControlState RenderThemeSafari::determineState(RenderObject* o) const
    112 {
    113     ThemeControlState result = 0;
    114     if (isActive(o))
    115         result |= SafariTheme::ActiveState;
    116     if (isEnabled(o) && !isReadOnlyControl(o))
    117         result |= SafariTheme::EnabledState;
    118     if (isPressed(o))
    119         result |= SafariTheme::PressedState;
    120     if (isChecked(o))
    121         result |= SafariTheme::CheckedState;
    122     if (isIndeterminate(o))
    123         result |= SafariTheme::IndeterminateCheckedState;
    124     if (isFocused(o))
    125         result |= SafariTheme::FocusedState;
    126     if (isDefault(o))
    127         result |= SafariTheme::DefaultState;
    128     return result;
    129 }
    130 
    131 static NSControlSize controlSizeFromRect(const IntRect& rect, const IntSize sizes[])
    132 {
    133     if (sizes[NSRegularControlSize].height() == rect.height())
    134         return NSRegularControlSize;
    135     else if (sizes[NSMiniControlSize].height() == rect.height())
    136         return NSMiniControlSize;
    137 
    138     return NSSmallControlSize;
    139 }
    140 
    141 RenderThemeSafari::RenderThemeSafari()
    142 {
    143 }
    144 
    145 RenderThemeSafari::~RenderThemeSafari()
    146 {
    147 }
    148 
    149 Color RenderThemeSafari::platformActiveSelectionBackgroundColor() const
    150 {
    151     return Color(181, 213, 255);
    152 }
    153 
    154 Color RenderThemeSafari::platformInactiveSelectionBackgroundColor() const
    155 {
    156     return Color(212, 212, 212);
    157 }
    158 
    159 Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const
    160 {
    161     // FIXME: This should probably just be a darker version of the platformActiveSelectionBackgroundColor
    162     return Color(56, 117, 215);
    163 }
    164 
    165 Color RenderThemeSafari::platformFocusRingColor() const
    166 {
    167     static Color focusRingColor;
    168 
    169     if (!focusRingColor.isValid()) {
    170         if (STCopyThemeColorPtr()) {
    171             RetainPtr<CGColorRef> color(AdoptCF, STCopyThemeColorPtr()(stFocusRingColorID, SafariTheme::ActiveState));
    172             focusRingColor = makeRGBAFromCGColor(color.get());
    173         }
    174         if (!focusRingColor.isValid())
    175             focusRingColor = aquaFocusRingColor;
    176     }
    177 
    178     return focusRingColor;
    179 }
    180 
    181 static float systemFontSizeForControlSize(NSControlSize controlSize)
    182 {
    183     static float sizes[] = { 13.0f, 11.0f, 9.0f };
    184 
    185     return sizes[controlSize];
    186 }
    187 
    188 void RenderThemeSafari::systemFont(int propId, FontDescription& fontDescription) const
    189 {
    190     static FontDescription systemFont;
    191     static FontDescription smallSystemFont;
    192     static FontDescription menuFont;
    193     static FontDescription labelFont;
    194     static FontDescription miniControlFont;
    195     static FontDescription smallControlFont;
    196     static FontDescription controlFont;
    197 
    198     FontDescription* cachedDesc;
    199     float fontSize = 0;
    200     switch (propId) {
    201         case CSSValueSmallCaption:
    202             cachedDesc = &smallSystemFont;
    203             if (!smallSystemFont.isAbsoluteSize())
    204                 fontSize = systemFontSizeForControlSize(NSSmallControlSize);
    205             break;
    206         case CSSValueMenu:
    207             cachedDesc = &menuFont;
    208             if (!menuFont.isAbsoluteSize())
    209                 fontSize = systemFontSizeForControlSize(NSRegularControlSize);
    210             break;
    211         case CSSValueStatusBar:
    212             cachedDesc = &labelFont;
    213             if (!labelFont.isAbsoluteSize())
    214                 fontSize = 10.0f;
    215             break;
    216         case CSSValueWebkitMiniControl:
    217             cachedDesc = &miniControlFont;
    218             if (!miniControlFont.isAbsoluteSize())
    219                 fontSize = systemFontSizeForControlSize(NSMiniControlSize);
    220             break;
    221         case CSSValueWebkitSmallControl:
    222             cachedDesc = &smallControlFont;
    223             if (!smallControlFont.isAbsoluteSize())
    224                 fontSize = systemFontSizeForControlSize(NSSmallControlSize);
    225             break;
    226         case CSSValueWebkitControl:
    227             cachedDesc = &controlFont;
    228             if (!controlFont.isAbsoluteSize())
    229                 fontSize = systemFontSizeForControlSize(NSRegularControlSize);
    230             break;
    231         default:
    232             cachedDesc = &systemFont;
    233             if (!systemFont.isAbsoluteSize())
    234                 fontSize = 13.0f;
    235     }
    236 
    237     if (fontSize) {
    238         cachedDesc->setIsAbsoluteSize(true);
    239         cachedDesc->setGenericFamily(FontDescription::NoFamily);
    240         cachedDesc->firstFamily().setFamily("Lucida Grande");
    241         cachedDesc->setSpecifiedSize(fontSize);
    242         cachedDesc->setWeight(FontWeightNormal);
    243         cachedDesc->setItalic(false);
    244     }
    245     fontDescription = *cachedDesc;
    246 }
    247 
    248 bool RenderThemeSafari::isControlStyled(const RenderStyle* style, const BorderData& border,
    249                                      const FillLayer& background, const Color& backgroundColor) const
    250 {
    251     // If we didn't find SafariTheme.dll we won't be able to paint any themed controls.
    252     if (!SafariThemeLibrary())
    253         return true;
    254 
    255     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart)
    256         return style->border() != border;
    257     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
    258 }
    259 
    260 void RenderThemeSafari::adjustRepaintRect(const RenderObject* o, IntRect& r)
    261 {
    262     NSControlSize controlSize = controlSizeForFont(o->style());
    263 
    264     switch (o->style()->appearance()) {
    265         case CheckboxPart: {
    266             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
    267             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
    268             r = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));
    269             break;
    270         }
    271         case RadioPart: {
    272             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
    273             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
    274             r = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));
    275             break;
    276         }
    277         case PushButtonPart:
    278         case DefaultButtonPart:
    279         case ButtonPart: {
    280             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
    281             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
    282             if (r.height() <= buttonSizes()[NSRegularControlSize].height())
    283                 r = inflateRect(r, buttonSizes()[controlSize], buttonMargins(controlSize));
    284             break;
    285         }
    286         case MenulistPart: {
    287             r = inflateRect(r, popupButtonSizes()[controlSize], popupButtonMargins(controlSize));
    288             break;
    289         }
    290         default:
    291             break;
    292     }
    293 }
    294 
    295 IntRect RenderThemeSafari::inflateRect(const IntRect& r, const IntSize& size, const int* margins) const
    296 {
    297     // Only do the inflation if the available width/height are too small.  Otherwise try to
    298     // fit the glow/check space into the available box's width/height.
    299     int widthDelta = r.width() - (size.width() + margins[leftMargin] + margins[rightMargin]);
    300     int heightDelta = r.height() - (size.height() + margins[topMargin] + margins[bottomMargin]);
    301     IntRect result(r);
    302     if (widthDelta < 0) {
    303         result.setX(result.x() - margins[leftMargin]);
    304         result.setWidth(result.width() - widthDelta);
    305     }
    306     if (heightDelta < 0) {
    307         result.setY(result.y() - margins[topMargin]);
    308         result.setHeight(result.height() - heightDelta);
    309     }
    310     return result;
    311 }
    312 
    313 int RenderThemeSafari::baselinePosition(const RenderObject* o) const
    314 {
    315     if (!o->isBox())
    316         return 0;
    317 
    318     if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) {
    319         const RenderBox* box = toRenderBox(o);
    320         return box->marginTop() + box->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
    321     }
    322 
    323     return RenderTheme::baselinePosition(o);
    324 }
    325 
    326 bool RenderThemeSafari::controlSupportsTints(const RenderObject* o) const
    327 {
    328     if (!isEnabled(o))
    329         return false;
    330 
    331     // Checkboxes only have tint when checked.
    332     if (o->style()->appearance() == CheckboxPart)
    333         return isChecked(o);
    334 
    335     // For now assume other controls have tint if enabled.
    336     return true;
    337 }
    338 
    339 NSControlSize RenderThemeSafari::controlSizeForFont(RenderStyle* style) const
    340 {
    341     int fontSize = style->fontSize();
    342     if (fontSize >= 16)
    343         return NSRegularControlSize;
    344     if (fontSize >= 11)
    345         return NSSmallControlSize;
    346     return NSMiniControlSize;
    347 }
    348 /*
    349 void RenderThemeSafari::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize)
    350 {
    351     NSControlSize size;
    352     if (minSize.width() >= sizes[NSRegularControlSize].width() &&
    353         minSize.height() >= sizes[NSRegularControlSize].height())
    354         size = NSRegularControlSize;
    355     else if (minSize.width() >= sizes[NSSmallControlSize].width() &&
    356              minSize.height() >= sizes[NSSmallControlSize].height())
    357         size = NSSmallControlSize;
    358     else
    359         size = NSMiniControlSize;
    360     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
    361         [cell setControlSize:size];
    362 }
    363 */
    364 IntSize RenderThemeSafari::sizeForFont(RenderStyle* style, const IntSize* sizes) const
    365 {
    366     return sizes[controlSizeForFont(style)];
    367 }
    368 
    369 IntSize RenderThemeSafari::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
    370 {
    371     return sizes[controlSizeForSystemFont(style)];
    372 }
    373 
    374 void RenderThemeSafari::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
    375 {
    376     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
    377     IntSize size = sizeForFont(style, sizes);
    378     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
    379         style->setWidth(Length(size.width(), Fixed));
    380     if (style->height().isAuto() && size.height() > 0)
    381         style->setHeight(Length(size.height(), Fixed));
    382 }
    383 
    384 void RenderThemeSafari::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
    385 {
    386     FontDescription fontDescription;
    387     fontDescription.setIsAbsoluteSize(true);
    388     fontDescription.setGenericFamily(FontDescription::SerifFamily);
    389 
    390     float fontSize = systemFontSizeForControlSize(controlSize);
    391     fontDescription.firstFamily().setFamily("Lucida Grande");
    392     fontDescription.setComputedSize(fontSize);
    393     fontDescription.setSpecifiedSize(fontSize);
    394 
    395     // Reset line height
    396     style->setLineHeight(RenderStyle::initialLineHeight());
    397 
    398     if (style->setFontDescription(fontDescription))
    399         style->font().update(selector->fontSelector());
    400 }
    401 
    402 NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle* style) const
    403 {
    404     int fontSize = style->fontSize();
    405     if (fontSize >= 13)
    406         return NSRegularControlSize;
    407     if (fontSize >= 11)
    408         return NSSmallControlSize;
    409     return NSMiniControlSize;
    410 }
    411 
    412 bool RenderThemeSafari::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    413 {
    414     ASSERT(SafariThemeLibrary());
    415 
    416     NSControlSize controlSize = controlSizeForFont(o->style());
    417 
    418     IntRect inflatedRect = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize));
    419     paintThemePart(SafariTheme::CheckboxPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
    420 
    421     return false;
    422 }
    423 
    424 const IntSize* RenderThemeSafari::checkboxSizes() const
    425 {
    426     static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
    427     return sizes;
    428 }
    429 
    430 const int* RenderThemeSafari::checkboxMargins(NSControlSize controlSize) const
    431 {
    432     static const int margins[3][4] =
    433     {
    434         { 2, 2, 2, 2 },
    435         { 2, 2, 2, 1 },
    436         { 1, 0, 0, 0 },
    437     };
    438     return margins[controlSize];
    439 }
    440 
    441 void RenderThemeSafari::setCheckboxSize(RenderStyle* style) const
    442 {
    443     // If the width and height are both specified, then we have nothing to do.
    444     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
    445         return;
    446 
    447     // Use the font size to determine the intrinsic width of the control.
    448     setSizeFromFont(style, checkboxSizes());
    449 }
    450 
    451 bool RenderThemeSafari::paintRadio(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    452 {
    453     ASSERT(SafariThemeLibrary());
    454 
    455     NSControlSize controlSize = controlSizeForFont(o->style());
    456 
    457     IntRect inflatedRect = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize));
    458     paintThemePart(RadioButtonPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
    459 
    460     return false;
    461 }
    462 
    463 const IntSize* RenderThemeSafari::radioSizes() const
    464 {
    465     static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
    466     return sizes;
    467 }
    468 
    469 const int* RenderThemeSafari::radioMargins(NSControlSize controlSize) const
    470 {
    471     static const int margins[3][4] =
    472     {
    473         { 1, 2, 2, 2 },
    474         { 0, 1, 2, 1 },
    475         { 0, 0, 1, 0 },
    476      };
    477     return margins[controlSize];
    478 }
    479 
    480 void RenderThemeSafari::setRadioSize(RenderStyle* style) const
    481 {
    482     // If the width and height are both specified, then we have nothing to do.
    483     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
    484         return;
    485 
    486     // Use the font size to determine the intrinsic width of the control.
    487     setSizeFromFont(style, radioSizes());
    488 }
    489 
    490 void RenderThemeSafari::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const
    491 {
    492     // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
    493     // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
    494     // by definition constrained, since we select mini only for small cramped environments.
    495     // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
    496     // padding.
    497     const int padding = 8;
    498     style->setPaddingLeft(Length(padding, Fixed));
    499     style->setPaddingRight(Length(padding, Fixed));
    500     style->setPaddingTop(Length(0, Fixed));
    501     style->setPaddingBottom(Length(0, Fixed));
    502 }
    503 
    504 void RenderThemeSafari::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
    505 {
    506     // There are three appearance constants for buttons.
    507     // (1) Push-button is the constant for the default Aqua system button.  Push buttons will not scale vertically and will not allow
    508     // custom fonts or colors.  <input>s use this constant.  This button will allow custom colors and font weights/variants but won't
    509     // scale vertically.
    510     // (2) square-button is the constant for the square button.  This button will allow custom fonts and colors and will scale vertically.
    511     // (3) Button is the constant that means "pick the best button as appropriate."  <button>s use this constant.  This button will
    512     // also scale vertically and allow custom fonts and colors.  It will attempt to use Aqua if possible and will make this determination
    513     // solely on the rectangle of the control.
    514 
    515     // Determine our control size based off our font.
    516     NSControlSize controlSize = controlSizeForFont(style);
    517 
    518     if (style->appearance() == PushButtonPart) {
    519         // Ditch the border.
    520         style->resetBorder();
    521 
    522         // Height is locked to auto.
    523         style->setHeight(Length(Auto));
    524 
    525         // White-space is locked to pre
    526         style->setWhiteSpace(PRE);
    527 
    528         // Set the button's vertical size.
    529         setButtonSize(style);
    530 
    531         // Add in the padding that we'd like to use.
    532         setButtonPaddingFromControlSize(style, controlSize);
    533 
    534         // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
    535         // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
    536         // system font for the control size instead.
    537         setFontFromControlSize(selector, style, controlSize);
    538     } else {
    539         // Set a min-height so that we can't get smaller than the mini button.
    540         style->setMinHeight(Length(15, Fixed));
    541 
    542         // Reset the top and bottom borders.
    543         style->resetBorderTop();
    544         style->resetBorderBottom();
    545     }
    546 }
    547 
    548 const IntSize* RenderThemeSafari::buttonSizes() const
    549 {
    550     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
    551     return sizes;
    552 }
    553 
    554 const int* RenderThemeSafari::buttonMargins(NSControlSize controlSize) const
    555 {
    556     static const int margins[3][4] =
    557     {
    558         { 4, 6, 7, 6 },
    559         { 4, 5, 6, 5 },
    560         { 0, 1, 1, 1 },
    561     };
    562     return margins[controlSize];
    563 }
    564 
    565 void RenderThemeSafari::setButtonSize(RenderStyle* style) const
    566 {
    567     // If the width and height are both specified, then we have nothing to do.
    568     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
    569         return;
    570 
    571     // Use the font size to determine the intrinsic width of the control.
    572     setSizeFromFont(style, buttonSizes());
    573 }
    574 
    575 bool RenderThemeSafari::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    576 {
    577     ASSERT(SafariThemeLibrary());
    578 
    579     // We inflate the rect as needed to account for padding included in the cell to accommodate the button
    580     // shadow.  We don't consider this part of the bounds of the control in WebKit.
    581 
    582     NSControlSize controlSize = controlSizeFromRect(r, buttonSizes());
    583     IntRect inflatedRect = r;
    584 
    585     ThemePart part;
    586     if (r.height() <= buttonSizes()[NSRegularControlSize].height()) {
    587         // Push button
    588         part = SafariTheme::PushButtonPart;
    589 
    590         IntSize size = buttonSizes()[controlSize];
    591         size.setWidth(r.width());
    592 
    593         // Center the button within the available space.
    594         if (inflatedRect.height() > size.height()) {
    595             inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
    596             inflatedRect.setHeight(size.height());
    597         }
    598 
    599         // Now inflate it to account for the shadow.
    600         inflatedRect = inflateRect(inflatedRect, size, buttonMargins(controlSize));
    601     } else
    602         part = SafariTheme::SquareButtonPart;
    603 
    604     paintThemePart(part, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o));
    605     return false;
    606 }
    607 
    608 bool RenderThemeSafari::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    609 {
    610     ASSERT(SafariThemeLibrary());
    611 
    612     paintThemePart(SafariTheme::TextFieldPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
    613     return false;
    614 }
    615 
    616 void RenderThemeSafari::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    617 {
    618 }
    619 
    620 bool RenderThemeSafari::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    621 {
    622 #if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 1
    623     ASSERT(SafariThemeLibrary());
    624 
    625     if (paintInfo.context->paintingDisabled())
    626         return true;
    627 
    628     paintThemePart(CapsLockPart, paintInfo.context->platformContext(), r, (NSControlSize)0, (ThemeControlState)0);
    629 
    630     return false;
    631 #else
    632     return true;
    633 #endif
    634 }
    635 
    636 bool RenderThemeSafari::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    637 {
    638     ASSERT(SafariThemeLibrary());
    639 
    640     paintThemePart(SafariTheme::TextAreaPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState);
    641     return false;
    642 }
    643 
    644 void RenderThemeSafari::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
    645 {
    646 }
    647 
    648 const int* RenderThemeSafari::popupButtonMargins(NSControlSize size) const
    649 {
    650     static const int margins[3][4] =
    651     {
    652         { 2, 3, 3, 3 },
    653         { 1, 3, 3, 3 },
    654         { 0, 1, 0, 1 }
    655     };
    656     return margins[size];
    657 }
    658 
    659 const IntSize* RenderThemeSafari::popupButtonSizes() const
    660 {
    661     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
    662     return sizes;
    663 }
    664 
    665 const int* RenderThemeSafari::popupButtonPadding(NSControlSize size) const
    666 {
    667     static const int padding[3][4] =
    668     {
    669         { 2, 26, 3, 8 },
    670         { 2, 23, 3, 8 },
    671         { 2, 22, 3, 10 }
    672     };
    673     return padding[size];
    674 }
    675 
    676 bool RenderThemeSafari::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& info, const IntRect& r)
    677 {
    678     ASSERT(SafariThemeLibrary());
    679 
    680     NSControlSize controlSize = controlSizeFromRect(r, popupButtonSizes());
    681     IntRect inflatedRect = r;
    682     IntSize size = popupButtonSizes()[controlSize];
    683     size.setWidth(r.width());
    684 
    685     // Now inflate it to account for the shadow.
    686     if (r.width() >= minimumMenuListSize(o->style()))
    687         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(controlSize));
    688 
    689     paintThemePart(DropDownButtonPart, info.context->platformContext(), inflatedRect, controlSize, determineState(o));
    690 
    691     return false;
    692 }
    693 
    694 const float baseFontSize = 11.0f;
    695 const float baseArrowHeight = 5.0f;
    696 const float baseArrowWidth = 7.0f;
    697 const int arrowPaddingLeft = 5;
    698 const int arrowPaddingRight = 5;
    699 const int paddingBeforeSeparator = 4;
    700 const int baseBorderRadius = 5;
    701 const int styledPopupPaddingLeft = 8;
    702 const int styledPopupPaddingTop = 1;
    703 const int styledPopupPaddingBottom = 2;
    704 
    705 static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
    706 {
    707     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
    708     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
    709     float a = inData[0];
    710     int i = 0;
    711     for (i = 0; i < 4; i++)
    712         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    713 }
    714 
    715 static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
    716 {
    717     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
    718     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
    719     float a = inData[0];
    720     int i = 0;
    721     for (i = 0; i < 4; i++)
    722         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    723 }
    724 
    725 static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
    726 {
    727     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
    728     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
    729     float a = inData[0];
    730     int i = 0;
    731     for (i = 0; i < 4; i++)
    732         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    733 }
    734 
    735 static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
    736 {
    737     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
    738     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
    739     float a = inData[0];
    740     int i = 0;
    741     for (i = 0; i < 4; i++)
    742         outData[i] = (1.0f - a) * dark[i] + a * light[i];
    743 }
    744 
    745 void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    746 {
    747     if (r.isEmpty())
    748         return;
    749 
    750     CGContextRef context = paintInfo.context->platformContext();
    751 
    752     paintInfo.context->save();
    753 
    754     IntSize topLeftRadius;
    755     IntSize topRightRadius;
    756     IntSize bottomLeftRadius;
    757     IntSize bottomRightRadius;
    758 
    759     o->style()->getBorderRadiiForRect(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    760 
    761     int radius = topLeftRadius.width();
    762 
    763     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
    764 
    765     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
    766     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
    767     RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
    768     RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
    769 
    770     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
    771     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
    772     RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
    773     RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
    774 
    775     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
    776     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
    777     RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
    778 
    779     RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
    780 
    781     RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
    782     paintInfo.context->save();
    783     CGContextClipToRect(context, r);
    784     paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    785     CGContextDrawShading(context, mainShading.get());
    786     paintInfo.context->restore();
    787 
    788     paintInfo.context->save();
    789     CGContextClipToRect(context, topGradient);
    790     paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient), topLeftRadius, topRightRadius, IntSize(), IntSize());
    791     CGContextDrawShading(context, topShading.get());
    792     paintInfo.context->restore();
    793 
    794     if (!bottomGradient.isEmpty()) {
    795         paintInfo.context->save();
    796         CGContextClipToRect(context, bottomGradient);
    797         paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bottomLeftRadius, bottomRightRadius);
    798         CGContextDrawShading(context, bottomShading.get());
    799         paintInfo.context->restore();
    800     }
    801 
    802     paintInfo.context->save();
    803     CGContextClipToRect(context, r);
    804     paintInfo.context->addRoundedRectClip(r, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius);
    805     CGContextDrawShading(context, leftShading.get());
    806     CGContextDrawShading(context, rightShading.get());
    807     paintInfo.context->restore();
    808 
    809     paintInfo.context->restore();
    810 }
    811 
    812 bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    813 {
    814     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
    815                              r.y() + o->style()->borderTopWidth(),
    816                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
    817                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
    818     // Draw the gradients to give the styled popup menu a button appearance
    819     paintMenuListButtonGradients(o, paintInfo, bounds);
    820 
    821     // Since we actually know the size of the control here, we restrict the font scale to make sure the arrow will fit vertically in the bounds
    822     float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / baseArrowHeight);
    823     float centerY = bounds.y() + bounds.height() / 2.0f;
    824     float arrowHeight = baseArrowHeight * fontScale;
    825     float arrowWidth = baseArrowWidth * fontScale;
    826     float leftEdge = bounds.right() - arrowPaddingRight - arrowWidth;
    827 
    828     if (bounds.width() < arrowWidth + arrowPaddingLeft)
    829         return false;
    830 
    831     paintInfo.context->save();
    832 
    833     paintInfo.context->setFillColor(o->style()->color(), DeviceColorSpace);
    834     paintInfo.context->setStrokeColor(NoStroke, DeviceColorSpace);
    835 
    836     FloatPoint arrow[3];
    837     arrow[0] = FloatPoint(leftEdge, centerY - arrowHeight / 2.0f);
    838     arrow[1] = FloatPoint(leftEdge + arrowWidth, centerY - arrowHeight / 2.0f);
    839     arrow[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + arrowHeight / 2.0f);
    840 
    841     // Draw the arrow
    842     paintInfo.context->drawConvexPolygon(3, arrow, true);
    843 
    844     Color leftSeparatorColor(0, 0, 0, 40);
    845     Color rightSeparatorColor(255, 255, 255, 40);
    846 
    847     // FIXME: Should the separator thickness and space be scaled up by fontScale?
    848     int separatorSpace = 2;
    849     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft); // FIXME: Round?
    850 
    851     // Draw the separator to the left of the arrows
    852     paintInfo.context->setStrokeThickness(1.0f);
    853     paintInfo.context->setStrokeStyle(SolidStroke);
    854     paintInfo.context->setStrokeColor(leftSeparatorColor, DeviceColorSpace);
    855     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
    856                                 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
    857 
    858     paintInfo.context->setStrokeColor(rightSeparatorColor, DeviceColorSpace);
    859     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
    860                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
    861 
    862     paintInfo.context->restore();
    863     return false;
    864 }
    865 
    866 void RenderThemeSafari::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
    867 {
    868     NSControlSize controlSize = controlSizeForFont(style);
    869 
    870     style->resetBorder();
    871     style->resetPadding();
    872 
    873     // Height is locked to auto.
    874     style->setHeight(Length(Auto));
    875 
    876     // White-space is locked to pre
    877     style->setWhiteSpace(PRE);
    878 
    879     // Set the foreground color to black or gray when we have the aqua look.
    880     // Cast to RGB32 is to work around a compiler bug.
    881     style->setColor(e && e->isEnabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
    882 
    883     // Set the button's vertical size.
    884     setButtonSize(style);
    885 
    886     // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
    887     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
    888     // system font for the control size instead.
    889     setFontFromControlSize(selector, style, controlSize);
    890 }
    891 
    892 int RenderThemeSafari::popupInternalPaddingLeft(RenderStyle* style) const
    893 {
    894     if (style->appearance() == MenulistPart)
    895         return popupButtonPadding(controlSizeForFont(style))[leftPadding];
    896     if (style->appearance() == MenulistButtonPart)
    897         return styledPopupPaddingLeft;
    898     return 0;
    899 }
    900 
    901 int RenderThemeSafari::popupInternalPaddingRight(RenderStyle* style) const
    902 {
    903     if (style->appearance() == MenulistPart)
    904         return popupButtonPadding(controlSizeForFont(style))[rightPadding];
    905     if (style->appearance() == MenulistButtonPart) {
    906         float fontScale = style->fontSize() / baseFontSize;
    907         float arrowWidth = baseArrowWidth * fontScale;
    908         return static_cast<int>(ceilf(arrowWidth + arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator));
    909     }
    910     return 0;
    911 }
    912 
    913 int RenderThemeSafari::popupInternalPaddingTop(RenderStyle* style) const
    914 {
    915     if (style->appearance() == MenulistPart)
    916         return popupButtonPadding(controlSizeForFont(style))[topPadding];
    917     if (style->appearance() == MenulistButtonPart)
    918         return styledPopupPaddingTop;
    919     return 0;
    920 }
    921 
    922 int RenderThemeSafari::popupInternalPaddingBottom(RenderStyle* style) const
    923 {
    924     if (style->appearance() == MenulistPart)
    925         return popupButtonPadding(controlSizeForFont(style))[bottomPadding];
    926     if (style->appearance() == MenulistButtonPart)
    927         return styledPopupPaddingBottom;
    928     return 0;
    929 }
    930 
    931 void RenderThemeSafari::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
    932 {
    933     float fontScale = style->fontSize() / baseFontSize;
    934 
    935     style->resetPadding();
    936     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
    937 
    938     const int minHeight = 15;
    939     style->setMinHeight(Length(minHeight, Fixed));
    940 
    941     style->setLineHeight(RenderStyle::initialLineHeight());
    942 }
    943 
    944 const IntSize* RenderThemeSafari::menuListSizes() const
    945 {
    946     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
    947     return sizes;
    948 }
    949 
    950 int RenderThemeSafari::minimumMenuListSize(RenderStyle* style) const
    951 {
    952     return sizeForSystemFont(style, menuListSizes()).width();
    953 }
    954 
    955 const int trackWidth = 5;
    956 const int trackRadius = 2;
    957 
    958 bool RenderThemeSafari::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
    959 {
    960     IntRect bounds = r;
    961 
    962     if (o->style()->appearance() ==  SliderHorizontalPart) {
    963         bounds.setHeight(trackWidth);
    964         bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
    965     } else if (o->style()->appearance() == SliderVerticalPart) {
    966         bounds.setWidth(trackWidth);
    967         bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
    968     }
    969 
    970     CGContextRef context = paintInfo.context->platformContext();
    971     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
    972 
    973     paintInfo.context->save();
    974     CGContextClipToRect(context, bounds);
    975 
    976     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
    977     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
    978     RetainPtr<CGShadingRef> mainShading;
    979     if (o->style()->appearance() == SliderVerticalPart)
    980         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
    981     else
    982         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
    983 
    984     IntSize radius(trackRadius, trackRadius);
    985     paintInfo.context->addRoundedRectClip(bounds,
    986         radius, radius,
    987         radius, radius);
    988     CGContextDrawShading(context, mainShading.get());
    989     paintInfo.context->restore();
    990 
    991     return false;
    992 }
    993 
    994 void RenderThemeSafari::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
    995 {
    996     style->setBoxShadow(0);
    997 }
    998 
    999 const float verticalSliderHeightPadding = 0.1f;
   1000 
   1001 bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1002 {
   1003     ASSERT(SafariThemeLibrary());
   1004 
   1005     ASSERT(o->parent()->isSlider());
   1006 
   1007     bool pressed = toRenderSlider(o->parent())->inDragMode();
   1008     ThemeControlState state = determineState(o->parent());
   1009     state &= ~SafariTheme::PressedState;
   1010     if (pressed)
   1011         state |= SafariTheme::PressedState;
   1012 
   1013     paintThemePart(SliderThumbPart, paintInfo.context->platformContext(), r, NSSmallControlSize, state);
   1014     return false;
   1015 }
   1016 
   1017 const int sliderThumbWidth = 15;
   1018 const int sliderThumbHeight = 15;
   1019 
   1020 void RenderThemeSafari::adjustSliderThumbSize(RenderObject* o) const
   1021 {
   1022     if (o->style()->appearance() == SliderThumbHorizontalPart || o->style()->appearance() == SliderThumbVerticalPart) {
   1023         o->style()->setWidth(Length(sliderThumbWidth, Fixed));
   1024         o->style()->setHeight(Length(sliderThumbHeight, Fixed));
   1025     }
   1026 #if ENABLE(VIDEO)
   1027     else if (o->style()->appearance() == MediaSliderThumbPart)
   1028         RenderMediaControls::adjustMediaSliderThumbSize(o);
   1029 #endif
   1030 }
   1031 
   1032 bool RenderThemeSafari::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1033 {
   1034     ASSERT(SafariThemeLibrary());
   1035 
   1036     paintThemePart(SafariTheme::SearchFieldPart, paintInfo.context->platformContext(), r, controlSizeFromRect(r, searchFieldSizes()), determineState(o));
   1037     return false;
   1038 }
   1039 
   1040 const IntSize* RenderThemeSafari::searchFieldSizes() const
   1041 {
   1042     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) };
   1043     return sizes;
   1044 }
   1045 
   1046 void RenderThemeSafari::setSearchFieldSize(RenderStyle* style) const
   1047 {
   1048     // If the width and height are both specified, then we have nothing to do.
   1049     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
   1050         return;
   1051 
   1052     // Use the font size to determine the intrinsic width of the control.
   1053     setSizeFromFont(style, searchFieldSizes());
   1054 }
   1055 
   1056 void RenderThemeSafari::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
   1057 {
   1058     // Override border.
   1059     style->resetBorder();
   1060     const short borderWidth = 2;
   1061     style->setBorderLeftWidth(borderWidth);
   1062     style->setBorderLeftStyle(INSET);
   1063     style->setBorderRightWidth(borderWidth);
   1064     style->setBorderRightStyle(INSET);
   1065     style->setBorderBottomWidth(borderWidth);
   1066     style->setBorderBottomStyle(INSET);
   1067     style->setBorderTopWidth(borderWidth);
   1068     style->setBorderTopStyle(INSET);
   1069 
   1070     // Override height.
   1071     style->setHeight(Length(Auto));
   1072     setSearchFieldSize(style);
   1073 
   1074     // Override padding size to match AppKit text positioning.
   1075     const int padding = 1;
   1076     style->setPaddingLeft(Length(padding, Fixed));
   1077     style->setPaddingRight(Length(padding, Fixed));
   1078     style->setPaddingTop(Length(padding, Fixed));
   1079     style->setPaddingBottom(Length(padding, Fixed));
   1080 
   1081     NSControlSize controlSize = controlSizeForFont(style);
   1082     setFontFromControlSize(selector, style, controlSize);
   1083 }
   1084 
   1085 bool RenderThemeSafari::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
   1086 {
   1087     ASSERT(SafariThemeLibrary());
   1088 
   1089     Node* input = o->node()->shadowAncestorNode();
   1090     ASSERT(input);
   1091     RenderObject* renderer = input->renderer();
   1092     ASSERT(renderer);
   1093 
   1094     IntRect searchRect = renderer->absoluteBoundingBoxRect();
   1095 
   1096     paintThemePart(SafariTheme::SearchFieldCancelButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
   1097     return false;
   1098 }
   1099 
   1100 const IntSize* RenderThemeSafari::cancelButtonSizes() const
   1101 {
   1102     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
   1103     return sizes;
   1104 }
   1105 
   1106 void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
   1107 {
   1108     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
   1109     style->setWidth(Length(size.width(), Fixed));
   1110     style->setHeight(Length(size.height(), Fixed));
   1111 }
   1112 
   1113 const IntSize* RenderThemeSafari::resultsButtonSizes() const
   1114 {
   1115     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
   1116     return sizes;
   1117 }
   1118 
   1119 const int emptyResultsOffset = 9;
   1120 void RenderThemeSafari::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
   1121 {
   1122     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1123     style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
   1124     style->setHeight(Length(size.height(), Fixed));
   1125 }
   1126 
   1127 bool RenderThemeSafari::paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&)
   1128 {
   1129     return false;
   1130 }
   1131 
   1132 void RenderThemeSafari::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
   1133 {
   1134     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1135     style->setWidth(Length(size.width(), Fixed));
   1136     style->setHeight(Length(size.height(), Fixed));
   1137 }
   1138 
   1139 bool RenderThemeSafari::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
   1140 {
   1141     ASSERT(SafariThemeLibrary());
   1142 
   1143     Node* input = o->node()->shadowAncestorNode();
   1144     ASSERT(input);
   1145     RenderObject* renderer = input->renderer();
   1146     ASSERT(renderer);
   1147 
   1148     IntRect searchRect = renderer->absoluteBoundingBoxRect();
   1149 
   1150     paintThemePart(SafariTheme::SearchFieldResultsDecorationPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
   1151     return false;
   1152 }
   1153 
   1154 const int resultsArrowWidth = 5;
   1155 void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
   1156 {
   1157     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
   1158     style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
   1159     style->setHeight(Length(size.height(), Fixed));
   1160 }
   1161 
   1162 bool RenderThemeSafari::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect&)
   1163 {
   1164     ASSERT(SafariThemeLibrary());
   1165 
   1166     Node* input = o->node()->shadowAncestorNode();
   1167     ASSERT(input);
   1168     RenderObject* renderer = input->renderer();
   1169     ASSERT(renderer);
   1170 
   1171     IntRect searchRect = renderer->absoluteBoundingBoxRect();
   1172 
   1173     paintThemePart(SafariTheme::SearchFieldResultsButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o));
   1174     return false;
   1175 }
   1176 #if ENABLE(VIDEO)
   1177 bool RenderThemeSafari::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1178 {
   1179     return RenderMediaControls::paintMediaControlsPart(MediaFullscreenButton, o, paintInfo, r);
   1180 }
   1181 
   1182 bool RenderThemeSafari::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1183 {
   1184     return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, o, paintInfo, r);
   1185 }
   1186 
   1187 bool RenderThemeSafari::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1188 {
   1189     return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, o, paintInfo, r);
   1190 }
   1191 
   1192 bool RenderThemeSafari::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1193 {
   1194     return RenderMediaControls::paintMediaControlsPart(MediaSeekBackButton, o, paintInfo, r);
   1195 }
   1196 
   1197 bool RenderThemeSafari::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1198 {
   1199     return RenderMediaControls::paintMediaControlsPart(MediaSeekForwardButton, o, paintInfo, r);
   1200 }
   1201 
   1202 bool RenderThemeSafari::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1203 {
   1204     return RenderMediaControls::paintMediaControlsPart(MediaSlider, o, paintInfo, r);
   1205 }
   1206 
   1207 bool RenderThemeSafari::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
   1208 {
   1209     return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r);
   1210 }
   1211 #endif
   1212 
   1213 } // namespace WebCore
   1214 
   1215 #endif // #if USE(SAFARI_THEME)
   1216