6fa92cdcd79776611be51e37d0a278ef8b387ad3
[WebKit-https.git] / WebCore / rendering / RenderThemeMac.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #import "config.h"
21 #import "RenderThemeMac.h"
22
23 #import "BitmapImage.h"
24 #import "CSSStyleSelector.h"
25 #import "CSSValueKeywords.h"
26 #import "Document.h"
27 #import "Element.h"
28 #import "FoundationExtras.h"
29 #import "FrameView.h"
30 #import "GraphicsContext.h"
31 #import "HTMLInputElement.h"
32 #import "HTMLMediaElement.h"
33 #import "HTMLNames.h"
34 #import "Image.h"
35 #import "LocalCurrentGraphicsContext.h"
36 #import "RenderSlider.h"
37 #import "RenderView.h"
38 #import "SharedBuffer.h"
39 #import "WebCoreSystemInterface.h"
40 #import <Cocoa/Cocoa.h>
41 #import <wtf/RetainPtr.h>
42 #import <math.h>
43
44 #ifdef BUILDING_ON_TIGER
45 typedef unsigned NSUInteger;
46 #endif
47
48 using std::min;
49
50 // The methods in this file are specific to the Mac OS X platform.
51
52 // FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeSafari. 
53
54 @interface WebCoreRenderThemeNotificationObserver : NSObject
55 {
56     WebCore::RenderTheme *_theme;
57 }
58
59 - (id)initWithTheme:(WebCore::RenderTheme *)theme;
60 - (void)systemColorsDidChange:(NSNotification *)notification;
61
62 @end
63
64 @implementation WebCoreRenderThemeNotificationObserver
65
66 - (id)initWithTheme:(WebCore::RenderTheme *)theme
67 {
68     [super init];
69     _theme = theme;
70     
71     return self;
72 }
73
74 - (void)systemColorsDidChange:(NSNotification *)notification
75 {
76     ASSERT([[notification name] isEqualToString:NSSystemColorsDidChangeNotification]);
77     _theme->platformColorsDidChange();
78 }
79
80 @end
81
82 namespace WebCore {
83
84 using namespace HTMLNames;
85
86 enum {
87     topMargin,
88     rightMargin,
89     bottomMargin,
90     leftMargin
91 };
92
93 enum {
94     topPadding,
95     rightPadding,
96     bottomPadding,
97     leftPadding
98 };
99
100 RenderTheme* theme()
101 {
102     static RenderThemeMac* macTheme = new RenderThemeMac;
103     return macTheme;
104 }
105
106 RenderThemeMac::RenderThemeMac()
107     : m_resizeCornerImage(0)
108     , m_mediaControlBackgroundImage(0)
109     , m_isSliderThumbHorizontalPressed(false)
110     , m_isSliderThumbVerticalPressed(false)
111     , m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
112 {
113     [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
114                                                         selector:@selector(systemColorsDidChange:)
115                                                             name:NSSystemColorsDidChangeNotification
116                                                           object:nil];
117 }
118
119 RenderThemeMac::~RenderThemeMac()
120 {
121     [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
122     delete m_resizeCornerImage;
123     delete m_mediaControlBackgroundImage;
124 }
125
126 Color RenderThemeMac::platformActiveSelectionBackgroundColor() const
127 {
128     NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
129     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
130 }
131
132 Color RenderThemeMac::platformInactiveSelectionBackgroundColor() const
133 {
134     NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
135     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
136 }
137
138 Color RenderThemeMac::activeListBoxSelectionBackgroundColor() const
139 {
140     NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
141     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
142 }
143
144 void RenderThemeMac::systemFont(int cssValueId, FontDescription& fontDescription) const
145 {
146     static FontDescription systemFont;
147     static FontDescription smallSystemFont;
148     static FontDescription menuFont;
149     static FontDescription labelFont;
150     static FontDescription miniControlFont;
151     static FontDescription smallControlFont;
152     static FontDescription controlFont;
153
154     FontDescription* cachedDesc;
155     NSFont* font = nil;
156     switch (cssValueId) {
157         case CSS_VAL_SMALL_CAPTION:
158             cachedDesc = &smallSystemFont;
159             if (!smallSystemFont.isAbsoluteSize())
160                 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
161             break;
162         case CSS_VAL_MENU:
163             cachedDesc = &menuFont;
164             if (!menuFont.isAbsoluteSize())
165                 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
166             break;
167         case CSS_VAL_STATUS_BAR:
168             cachedDesc = &labelFont;
169             if (!labelFont.isAbsoluteSize())
170                 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
171             break;
172         case CSS_VAL__WEBKIT_MINI_CONTROL:
173             cachedDesc = &miniControlFont;
174             if (!miniControlFont.isAbsoluteSize())
175                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
176             break;
177         case CSS_VAL__WEBKIT_SMALL_CONTROL:
178             cachedDesc = &smallControlFont;
179             if (!smallControlFont.isAbsoluteSize())
180                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
181             break;
182         case CSS_VAL__WEBKIT_CONTROL:
183             cachedDesc = &controlFont;
184             if (!controlFont.isAbsoluteSize())
185                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
186             break;
187         default:
188             cachedDesc = &systemFont;
189             if (!systemFont.isAbsoluteSize())
190                 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
191     }
192
193     if (font) {
194         cachedDesc->setIsAbsoluteSize(true);
195         cachedDesc->setGenericFamily(FontDescription::NoFamily);
196         cachedDesc->firstFamily().setFamily([font familyName]);
197         cachedDesc->setSpecifiedSize([font pointSize]);
198         NSFontTraitMask traits = [[NSFontManager sharedFontManager] traitsOfFont:font];
199         cachedDesc->setBold(traits & NSBoldFontMask);
200         cachedDesc->setItalic(traits & NSItalicFontMask);
201     }
202     fontDescription = *cachedDesc;
203 }
204
205 static RGBA32 convertNSColorToColor(NSColor *color)
206 {
207     NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
208     if (colorInColorSpace) {
209         static const double scaleFactor = nextafter(256.0, 0.0);
210         return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
211             static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
212             static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
213     }
214
215     // This conversion above can fail if the NSColor in question is an NSPatternColor 
216     // (as many system colors are). These colors are actually a repeating pattern
217     // not just a solid color. To work around this we simply draw a 1x1 image of
218     // the color and use that pixel's color. It might be better to use an average of
219     // the colors in the pattern instead.
220     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
221                                                                              pixelsWide:1
222                                                                              pixelsHigh:1
223                                                                           bitsPerSample:8
224                                                                         samplesPerPixel:4
225                                                                                hasAlpha:YES
226                                                                                isPlanar:NO
227                                                                          colorSpaceName:NSCalibratedRGBColorSpace
228                                                                             bytesPerRow:4
229                                                                            bitsPerPixel:32];
230
231     [NSGraphicsContext saveGraphicsState];
232     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
233     NSEraseRect(NSMakeRect(0, 0, 1, 1));
234     [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
235     [NSGraphicsContext restoreGraphicsState];
236
237     NSUInteger pixel[4];
238     [offscreenRep getPixel:pixel atX:0 y:0];
239
240     [offscreenRep release];
241
242     return makeRGB(pixel[0], pixel[1], pixel[2]);
243 }
244
245 void RenderThemeMac::platformColorsDidChange()
246 {
247     m_systemColorCache.clear();
248     RenderTheme::platformColorsDidChange();
249 }
250
251 Color RenderThemeMac::systemColor(int cssValueId) const
252 {
253     if (m_systemColorCache.contains(cssValueId))
254         return m_systemColorCache.get(cssValueId);
255     
256     Color color;
257     switch (cssValueId) {
258         case CSS_VAL_ACTIVEBORDER:
259             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
260             break;
261         case CSS_VAL_ACTIVECAPTION:
262             color = convertNSColorToColor([NSColor windowFrameTextColor]);
263             break;
264         case CSS_VAL_APPWORKSPACE:
265             color = convertNSColorToColor([NSColor headerColor]);
266             break;
267         case CSS_VAL_BACKGROUND:
268             // Use theme independent default
269             break;
270         case CSS_VAL_BUTTONFACE:
271             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
272             // We may want to change this to use the NSColor in future.
273             color = 0xFFC0C0C0;
274             break;
275         case CSS_VAL_BUTTONHIGHLIGHT:
276             color = convertNSColorToColor([NSColor controlHighlightColor]);
277             break;
278         case CSS_VAL_BUTTONSHADOW:
279             color = convertNSColorToColor([NSColor controlShadowColor]);
280             break;
281         case CSS_VAL_BUTTONTEXT:
282             color = convertNSColorToColor([NSColor controlTextColor]);
283             break;
284         case CSS_VAL_CAPTIONTEXT:
285             color = convertNSColorToColor([NSColor textColor]);
286             break;
287         case CSS_VAL_GRAYTEXT:
288             color = convertNSColorToColor([NSColor disabledControlTextColor]);
289             break;
290         case CSS_VAL_HIGHLIGHT:
291             color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
292             break;
293         case CSS_VAL_HIGHLIGHTTEXT:
294             color = convertNSColorToColor([NSColor selectedTextColor]);
295             break;
296         case CSS_VAL_INACTIVEBORDER:
297             color = convertNSColorToColor([NSColor controlBackgroundColor]);
298             break;
299         case CSS_VAL_INACTIVECAPTION:
300             color = convertNSColorToColor([NSColor controlBackgroundColor]);
301             break;
302         case CSS_VAL_INACTIVECAPTIONTEXT:
303             color = convertNSColorToColor([NSColor textColor]);
304             break;
305         case CSS_VAL_INFOBACKGROUND:
306             // There is no corresponding NSColor for this so we use a hard coded value.
307             color = 0xFFFBFCC5;
308             break;
309         case CSS_VAL_INFOTEXT:
310             color = convertNSColorToColor([NSColor textColor]);
311             break;
312         case CSS_VAL_MENU:
313             color = convertNSColorToColor([NSColor selectedMenuItemColor]);
314             break;
315         case CSS_VAL_MENUTEXT:
316             color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
317             break;
318         case CSS_VAL_SCROLLBAR:
319             color = convertNSColorToColor([NSColor scrollBarColor]);
320             break;
321         case CSS_VAL_TEXT:
322             color = convertNSColorToColor([NSColor textColor]);
323             break;
324         case CSS_VAL_THREEDDARKSHADOW:
325             color = convertNSColorToColor([NSColor controlDarkShadowColor]);
326             break;
327         case CSS_VAL_THREEDSHADOW:
328             color = convertNSColorToColor([NSColor shadowColor]);
329             break;
330         case CSS_VAL_THREEDFACE:
331             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
332             // We may want to change this to use the NSColor in future.
333             color = 0xFFC0C0C0;
334             break;
335         case CSS_VAL_THREEDHIGHLIGHT:
336             color = convertNSColorToColor([NSColor highlightColor]);
337             break;
338         case CSS_VAL_THREEDLIGHTSHADOW:
339             color = convertNSColorToColor([NSColor controlLightHighlightColor]);
340             break;
341         case CSS_VAL_WINDOW:
342             color = convertNSColorToColor([NSColor windowBackgroundColor]);
343             break;
344         case CSS_VAL_WINDOWFRAME:
345             color = convertNSColorToColor([NSColor windowFrameColor]);
346             break;
347         case CSS_VAL_WINDOWTEXT:
348             color = convertNSColorToColor([NSColor windowFrameTextColor]);
349             break;
350     }
351
352     if (!color.isValid())
353         color = RenderTheme::systemColor(cssValueId);
354
355     if (color.isValid())
356         m_systemColorCache.set(cssValueId, color.rgb());
357
358     return color;
359 }
360
361 bool RenderThemeMac::isControlStyled(const RenderStyle* style, const BorderData& border,
362                                      const BackgroundLayer& background, const Color& backgroundColor) const
363 {
364     if (style->appearance() == TextFieldAppearance || style->appearance() == TextAreaAppearance || style->appearance() == ListboxAppearance)
365         return style->border() != border;
366     return RenderTheme::isControlStyled(style, border, background, backgroundColor);
367 }
368
369 void RenderThemeMac::paintResizeControl(GraphicsContext* c, const IntRect& r)
370 {
371     Image* resizeCornerImage = this->resizeCornerImage();
372     IntPoint imagePoint(r.right() - resizeCornerImage->width(), r.bottom() - resizeCornerImage->height());
373     c->drawImage(resizeCornerImage, imagePoint);
374 }
375
376 void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
377 {
378     switch (o->style()->appearance()) {
379         case CheckboxAppearance: {
380             // Since we query the prototype cell, we need to update its state to match.
381             setCheckboxCellState(o, r);
382
383             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
384             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
385             r = inflateRect(r, checkboxSizes()[[checkbox() controlSize]], checkboxMargins());
386             break;
387         }
388         case RadioAppearance: {
389             // Since we query the prototype cell, we need to update its state to match.
390             setRadioCellState(o, r);
391
392             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
393             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
394             r = inflateRect(r, radioSizes()[[radio() controlSize]], radioMargins());
395             break;
396         }
397         case PushButtonAppearance:
398         case ButtonAppearance: {
399             // Since we query the prototype cell, we need to update its state to match.
400             setButtonCellState(o, r);
401
402             // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
403             // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
404             if ([button() bezelStyle] == NSRoundedBezelStyle)
405                 r = inflateRect(r, buttonSizes()[[button() controlSize]], buttonMargins());
406             break;
407         }
408         case MenulistAppearance: {
409             setPopupButtonCellState(o, r);
410             r = inflateRect(r, popupButtonSizes()[[popupButton() controlSize]], popupButtonMargins());
411             break;
412         }
413         default:
414             break;
415     }
416 }
417
418 IntRect RenderThemeMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins) const
419 {
420     // Only do the inflation if the available width/height are too small.  Otherwise try to
421     // fit the glow/check space into the available box's width/height.
422     int widthDelta = r.width() - (size.width() + margins[leftMargin] + margins[rightMargin]);
423     int heightDelta = r.height() - (size.height() + margins[topMargin] + margins[bottomMargin]);
424     IntRect result(r);
425     if (widthDelta < 0) {
426         result.setX(result.x() - margins[leftMargin]);
427         result.setWidth(result.width() - widthDelta);
428     }
429     if (heightDelta < 0) {
430         result.setY(result.y() - margins[topMargin]);
431         result.setHeight(result.height() - heightDelta);
432     }
433     return result;
434 }
435
436 void RenderThemeMac::updateCheckedState(NSCell* cell, const RenderObject* o)
437 {
438     bool oldIndeterminate = [cell state] == NSMixedState;
439     bool indeterminate = isIndeterminate(o);
440     bool checked = isChecked(o);
441
442     if (oldIndeterminate != indeterminate) {
443         [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
444         return;
445     }
446
447     bool oldChecked = [cell state] == NSOnState;
448     if (checked != oldChecked)
449         [cell setState:checked ? NSOnState : NSOffState];
450 }
451
452 void RenderThemeMac::updateEnabledState(NSCell* cell, const RenderObject* o)
453 {
454     bool oldEnabled = [cell isEnabled];
455     bool enabled = isEnabled(o);
456     if (enabled != oldEnabled)
457         [cell setEnabled:enabled];
458 }
459
460 void RenderThemeMac::updateFocusedState(NSCell* cell, const RenderObject* o)
461 {
462     bool oldFocused = [cell showsFirstResponder];
463     bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
464     if (focused != oldFocused)
465         [cell setShowsFirstResponder:focused];
466 }
467
468 void RenderThemeMac::updatePressedState(NSCell* cell, const RenderObject* o)
469 {
470     bool oldPressed = [cell isHighlighted];
471     bool pressed = (o->element() && o->element()->active());
472     if (pressed != oldPressed)
473         [cell setHighlighted:pressed];
474 }
475
476 short RenderThemeMac::baselinePosition(const RenderObject* o) const
477 {
478     if (o->style()->appearance() == CheckboxAppearance || o->style()->appearance() == RadioAppearance)
479         return o->marginTop() + o->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit.
480     return RenderTheme::baselinePosition(o);
481 }
482
483 bool RenderThemeMac::controlSupportsTints(const RenderObject* o) const
484 {
485     // An alternate way to implement this would be to get the appropriate cell object
486     // and call the private _needRedrawOnWindowChangedKeyState method. An advantage of
487     // that would be that we would match AppKit behavior more closely, but a disadvantage
488     // would be that we would rely on an AppKit SPI method.
489
490     if (!isEnabled(o))
491         return false;
492
493     // Checkboxes only have tint when checked.
494     if (o->style()->appearance() == CheckboxAppearance)
495         return isChecked(o);
496
497     // For now assume other controls have tint if enabled.
498     return true;
499 }
500
501 NSControlSize RenderThemeMac::controlSizeForFont(RenderStyle* style) const
502 {
503     int fontSize = style->fontSize();
504     if (fontSize >= 16)
505         return NSRegularControlSize;
506     if (fontSize >= 11)
507         return NSSmallControlSize;
508     return NSMiniControlSize;
509 }
510
511 void RenderThemeMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize)
512 {
513     NSControlSize size;
514     if (minSize.width() >= sizes[NSRegularControlSize].width() &&
515         minSize.height() >= sizes[NSRegularControlSize].height())
516         size = NSRegularControlSize;
517     else if (minSize.width() >= sizes[NSSmallControlSize].width() &&
518              minSize.height() >= sizes[NSSmallControlSize].height())
519         size = NSSmallControlSize;
520     else
521         size = NSMiniControlSize;
522     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
523         [cell setControlSize:size];
524 }
525
526 IntSize RenderThemeMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
527 {
528     return sizes[controlSizeForFont(style)];
529 }
530
531 IntSize RenderThemeMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
532 {
533     return sizes[controlSizeForSystemFont(style)];
534 }
535
536 void RenderThemeMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
537 {
538     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
539     IntSize size = sizeForFont(style, sizes);
540     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
541         style->setWidth(Length(size.width(), Fixed));
542     if (style->height().isAuto() && size.height() > 0)
543         style->setHeight(Length(size.height(), Fixed));
544 }
545
546 void RenderThemeMac::setFontFromControlSize(CSSStyleSelector* selector, RenderStyle* style, NSControlSize controlSize) const
547 {
548     FontDescription fontDescription;
549     fontDescription.setIsAbsoluteSize(true);
550     fontDescription.setGenericFamily(FontDescription::SerifFamily);
551
552     NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
553     fontDescription.firstFamily().setFamily([font familyName]);
554     fontDescription.setComputedSize([font pointSize]);
555     fontDescription.setSpecifiedSize([font pointSize]);
556
557     // Reset line height
558     style->setLineHeight(RenderStyle::initialLineHeight());
559
560     if (style->setFontDescription(fontDescription))
561         style->font().update(0);
562 }
563
564 NSControlSize RenderThemeMac::controlSizeForSystemFont(RenderStyle* style) const
565 {
566     int fontSize = style->fontSize();
567     if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
568         return NSRegularControlSize;
569     if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
570         return NSSmallControlSize;
571     return NSMiniControlSize;
572 }
573
574 bool RenderThemeMac::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
575 {
576     // Determine the width and height needed for the control and prepare the cell for painting.
577     setCheckboxCellState(o, r);
578
579     // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
580     // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
581     NSButtonCell* checkbox = this->checkbox();
582     IntRect inflatedRect = inflateRect(r, checkboxSizes()[[checkbox controlSize]], checkboxMargins());
583     [checkbox drawWithFrame:NSRect(inflatedRect) inView:o->view()->frameView()->getDocumentView()];
584     [checkbox setControlView:nil];
585
586     return false;
587 }
588
589 const IntSize* RenderThemeMac::checkboxSizes() const
590 {
591     static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) };
592     return sizes;
593 }
594
595 const int* RenderThemeMac::checkboxMargins() const
596 {
597     static const int margins[3][4] =
598     {
599         { 3, 4, 4, 2 },
600         { 4, 3, 3, 3 },
601         { 4, 3, 3, 3 },
602     };
603     return margins[[checkbox() controlSize]];
604 }
605
606 void RenderThemeMac::setCheckboxCellState(const RenderObject* o, const IntRect& r)
607 {
608     NSButtonCell* checkbox = this->checkbox();
609
610     // Set the control size based off the rectangle we're painting into.
611     setControlSize(checkbox, checkboxSizes(), r.size());
612
613     // Update the various states we respond to.
614     updateCheckedState(checkbox, o);
615     updateEnabledState(checkbox, o);
616     updatePressedState(checkbox, o);
617     updateFocusedState(checkbox, o);
618 }
619
620 void RenderThemeMac::setCheckboxSize(RenderStyle* style) const
621 {
622     // If the width and height are both specified, then we have nothing to do.
623     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
624         return;
625
626     // Use the font size to determine the intrinsic width of the control.
627     setSizeFromFont(style, checkboxSizes());
628 }
629
630 bool RenderThemeMac::paintRadio(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
631 {
632     // Determine the width and height needed for the control and prepare the cell for painting.
633     setRadioCellState(o, r);
634
635     // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox
636     // shadow" and the check.  We don't consider this part of the bounds of the control in WebKit.
637     NSButtonCell* radio = this->radio();
638     IntRect inflatedRect = inflateRect(r, radioSizes()[[radio controlSize]], radioMargins());
639     [radio drawWithFrame:NSRect(inflatedRect) inView:o->view()->frameView()->getDocumentView()];
640     [radio setControlView:nil];
641
642     return false;
643 }
644
645 const IntSize* RenderThemeMac::radioSizes() const
646 {
647     static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) };
648     return sizes;
649 }
650
651 const int* RenderThemeMac::radioMargins() const
652 {
653     static const int margins[3][4] =
654     {
655         { 2, 2, 4, 2 },
656         { 3, 2, 3, 2 },
657         { 1, 0, 2, 0 },
658     };
659     return margins[[radio() controlSize]];
660 }
661
662 void RenderThemeMac::setRadioCellState(const RenderObject* o, const IntRect& r)
663 {
664     NSButtonCell* radio = this->radio();
665
666     // Set the control size based off the rectangle we're painting into.
667     setControlSize(radio, radioSizes(), r.size());
668
669     // Update the various states we respond to.
670     updateCheckedState(radio, o);
671     updateEnabledState(radio, o);
672     updatePressedState(radio, o);
673     updateFocusedState(radio, o);
674 }
675
676
677 void RenderThemeMac::setRadioSize(RenderStyle* style) const
678 {
679     // If the width and height are both specified, then we have nothing to do.
680     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
681         return;
682
683     // Use the font size to determine the intrinsic width of the control.
684     setSizeFromFont(style, radioSizes());
685 }
686
687 void RenderThemeMac::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const
688 {
689     // Just use 8px.  AppKit wants to use 11px for mini buttons, but that padding is just too large
690     // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is
691     // by definition constrained, since we select mini only for small cramped environments.
692     // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent
693     // padding.
694     const int padding = 8;
695     style->setPaddingLeft(Length(padding, Fixed));
696     style->setPaddingRight(Length(padding, Fixed));
697     style->setPaddingTop(Length(0, Fixed));
698     style->setPaddingBottom(Length(0, Fixed));
699 }
700
701 void RenderThemeMac::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
702 {
703     // There are three appearance constants for buttons.
704     // (1) Push-button is the constant for the default Aqua system button.  Push buttons will not scale vertically and will not allow
705     // custom fonts or colors.  <input>s use this constant.  This button will allow custom colors and font weights/variants but won't
706     // scale vertically.
707     // (2) square-button is the constant for the square button.  This button will allow custom fonts and colors and will scale vertically.
708     // (3) Button is the constant that means "pick the best button as appropriate."  <button>s use this constant.  This button will
709     // also scale vertically and allow custom fonts and colors.  It will attempt to use Aqua if possible and will make this determination
710     // solely on the rectangle of the control.
711
712     // Determine our control size based off our font.
713     NSControlSize controlSize = controlSizeForFont(style);
714
715     if (style->appearance() == PushButtonAppearance) {
716         // Ditch the border.
717         style->resetBorder();
718
719         // Height is locked to auto.
720         style->setHeight(Length(Auto));
721
722         // White-space is locked to pre
723         style->setWhiteSpace(PRE);
724
725         // Set the button's vertical size.
726         setButtonSize(style);
727
728         // Add in the padding that we'd like to use.
729         setButtonPaddingFromControlSize(style, controlSize);
730
731         // 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
732         // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
733         // system font for the control size instead.
734         setFontFromControlSize(selector, style, controlSize);
735     } else {
736         // Set a min-height so that we can't get smaller than the mini button.
737         style->setMinHeight(Length(15, Fixed));
738
739         // Reset the top and bottom borders.
740         style->resetBorderTop();
741         style->resetBorderBottom();
742     }
743
744     style->setBoxShadow(0);
745 }
746
747 const IntSize* RenderThemeMac::buttonSizes() const
748 {
749     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
750     return sizes;
751 }
752
753 const int* RenderThemeMac::buttonMargins() const
754 {
755     static const int margins[3][4] =
756     {
757         { 4, 6, 7, 6 },
758         { 4, 5, 6, 5 },
759         { 0, 1, 1, 1 },
760     };
761     return margins[[button() controlSize]];
762 }
763
764 void RenderThemeMac::setButtonSize(RenderStyle* style) const
765 {
766     // If the width and height are both specified, then we have nothing to do.
767     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
768         return;
769
770     // Use the font size to determine the intrinsic width of the control.
771     setSizeFromFont(style, buttonSizes());
772 }
773
774 void RenderThemeMac::setButtonCellState(const RenderObject* o, const IntRect& r)
775 {
776     NSButtonCell* button = this->button();
777
778     // Set the control size based off the rectangle we're painting into.
779     if (o->style()->appearance() == SquareButtonAppearance ||
780         r.height() > buttonSizes()[NSRegularControlSize].height()) {
781         // Use the square button
782         if ([button bezelStyle] != NSShadowlessSquareBezelStyle)
783             [button setBezelStyle:NSShadowlessSquareBezelStyle];
784     } else if ([button bezelStyle] != NSRoundedBezelStyle)
785         [button setBezelStyle:NSRoundedBezelStyle];
786
787     setControlSize(button, buttonSizes(), r.size());
788
789     // Update the various states we respond to.
790     updateCheckedState(button, o);
791     updateEnabledState(button, o);
792     updatePressedState(button, o);
793     updateFocusedState(button, o);
794 }
795
796 bool RenderThemeMac::paintButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
797 {
798     NSButtonCell* button = this->button();
799     LocalCurrentGraphicsContext localContext(paintInfo.context);
800
801     // Determine the width and height needed for the control and prepare the cell for painting.
802     setButtonCellState(o, r);
803
804     // We inflate the rect as needed to account for padding included in the cell to accommodate the button
805     // shadow.  We don't consider this part of the bounds of the control in WebKit.
806     IntSize size = buttonSizes()[[button controlSize]];
807     size.setWidth(r.width());
808     IntRect inflatedRect = r;
809     if ([button bezelStyle] == NSRoundedBezelStyle) {
810         // Center the button within the available space.
811         if (inflatedRect.height() > size.height()) {
812             inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2);
813             inflatedRect.setHeight(size.height());
814         }
815
816         // Now inflate it to account for the shadow.
817         inflatedRect = inflateRect(inflatedRect, size, buttonMargins());
818     }
819
820     [button drawWithFrame:NSRect(inflatedRect) inView:o->view()->frameView()->getDocumentView()];
821     [button setControlView:nil];
822
823     return false;
824 }
825
826 bool RenderThemeMac::paintTextField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
827 {
828     LocalCurrentGraphicsContext localContext(paintInfo.context);
829     wkDrawBezeledTextFieldCell(r, isEnabled(o) && !isReadOnlyControl(o));
830     return false;
831 }
832
833 void RenderThemeMac::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const
834 {
835 }
836
837 bool RenderThemeMac::paintCapsLockIndicator(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
838 {
839     if (paintInfo.context->paintingDisabled())
840         return true;
841
842     LocalCurrentGraphicsContext localContext(paintInfo.context);
843     wkDrawCapsLockIndicator(paintInfo.context->platformContext(), r);
844     
845     return false;
846 }
847
848 bool RenderThemeMac::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
849 {
850     LocalCurrentGraphicsContext localContext(paintInfo.context);
851     wkDrawBezeledTextArea(r, isEnabled(o) && !isReadOnlyControl(o));
852     return false;
853 }
854
855 void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const
856 {
857 }
858
859 const int* RenderThemeMac::popupButtonMargins() const
860 {
861     static const int margins[3][4] =
862     {
863         { 0, 3, 1, 3 },
864         { 0, 3, 2, 3 },
865         { 0, 1, 0, 1 }
866     };
867     return margins[[popupButton() controlSize]];
868 }
869
870 const IntSize* RenderThemeMac::popupButtonSizes() const
871 {
872     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
873     return sizes;
874 }
875
876 const int* RenderThemeMac::popupButtonPadding(NSControlSize size) const
877 {
878     static const int padding[3][4] =
879     {
880         { 2, 26, 3, 8 },
881         { 2, 23, 3, 8 },
882         { 2, 22, 3, 10 }
883     };
884     return padding[size];
885 }
886
887 bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
888 {
889     setPopupButtonCellState(o, r);
890
891     NSPopUpButtonCell* popupButton = this->popupButton();
892
893     IntRect inflatedRect = r;
894     IntSize size = popupButtonSizes()[[popupButton controlSize]];
895     size.setWidth(r.width());
896
897     // Now inflate it to account for the shadow.
898     if (r.width() >= minimumMenuListSize(o->style()))
899         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins());
900
901 #ifndef BUILDING_ON_TIGER
902     // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
903     paintInfo.context->save();
904     paintInfo.context->clip(inflatedRect);
905 #endif
906
907     [popupButton drawWithFrame:inflatedRect inView:o->view()->frameView()->getDocumentView()];
908     [popupButton setControlView:nil];
909
910 #ifndef BUILDING_ON_TIGER
911     paintInfo.context->restore();
912 #endif
913
914     return false;
915 }
916
917 const float baseFontSize = 11.0f;
918 const float baseArrowHeight = 4.0f;
919 const float baseArrowWidth = 5.0f;
920 const float baseSpaceBetweenArrows = 2.0f;
921 const int arrowPaddingLeft = 6;
922 const int arrowPaddingRight = 6;
923 const int paddingBeforeSeparator = 4;
924 const int baseBorderRadius = 5;
925 const int styledPopupPaddingLeft = 8;
926 const int styledPopupPaddingTop = 1;
927 const int styledPopupPaddingBottom = 2;
928
929 static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
930 {
931     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f };
932     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f };
933     float a = inData[0];
934     int i = 0;
935     for (i = 0; i < 4; i++)
936         outData[i] = (1.0f - a) * dark[i] + a * light[i];
937 }
938
939 static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
940 {
941     static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f };
942     static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f };
943     float a = inData[0];
944     int i = 0;
945     for (i = 0; i < 4; i++)
946         outData[i] = (1.0f - a) * dark[i] + a * light[i];
947 }
948
949 static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
950 {
951     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f };
952     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
953     float a = inData[0];
954     int i = 0;
955     for (i = 0; i < 4; i++)
956         outData[i] = (1.0f - a) * dark[i] + a * light[i];
957 }
958
959 static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData)
960 {
961     static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f };
962     static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f };
963     float a = inData[0];
964     int i = 0;
965     for (i = 0; i < 4; i++)
966         outData[i] = (1.0f - a) * dark[i] + a * light[i];
967 }
968
969 void RenderThemeMac::paintMenuListButtonGradients(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
970 {
971     CGContextRef context = paintInfo.context->platformContext();
972
973     paintInfo.context->save();
974
975     int radius = o->style()->borderTopLeftRadius().width();
976
977     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
978
979     FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f);
980     struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL };
981     RetainPtr<CGFunctionRef> topFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks));
982     RetainPtr<CGShadingRef> topShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.bottom()), topFunction.get(), false, false));
983
984     FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f);
985     struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL };
986     RetainPtr<CGFunctionRef> bottomFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks));
987     RetainPtr<CGShadingRef> bottomShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.bottom()), bottomFunction.get(), false, false));
988
989     struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL };
990     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
991     RetainPtr<CGShadingRef> mainShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.bottom()), mainFunction.get(), false, false));
992
993     RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
994
995     RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace.get(), CGPointMake(r.right(),  r.y()), CGPointMake(r.right() - radius, r.y()), mainFunction.get(), false, false));
996     paintInfo.context->save();
997     CGContextClipToRect(context, r);
998     paintInfo.context->addRoundedRectClip(r,
999         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1000         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1001     CGContextDrawShading(context, mainShading.get());
1002     paintInfo.context->restore();
1003
1004     paintInfo.context->save();
1005     CGContextClipToRect(context, topGradient);
1006     paintInfo.context->addRoundedRectClip(enclosingIntRect(topGradient),
1007         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1008         IntSize(), IntSize());
1009     CGContextDrawShading(context, topShading.get());
1010     paintInfo.context->restore();
1011
1012     paintInfo.context->save();
1013     CGContextClipToRect(context, bottomGradient);
1014     paintInfo.context->addRoundedRectClip(enclosingIntRect(bottomGradient),
1015         IntSize(), IntSize(),
1016         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1017     CGContextDrawShading(context, bottomShading.get());
1018     paintInfo.context->restore();
1019
1020     paintInfo.context->save();
1021     CGContextClipToRect(context, r);
1022     paintInfo.context->addRoundedRectClip(r,
1023         o->style()->borderTopLeftRadius(), o->style()->borderTopRightRadius(),
1024         o->style()->borderBottomLeftRadius(), o->style()->borderBottomRightRadius());
1025     CGContextDrawShading(context, leftShading.get());
1026     CGContextDrawShading(context, rightShading.get());
1027     paintInfo.context->restore();
1028
1029     paintInfo.context->restore();
1030 }
1031
1032 bool RenderThemeMac::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1033 {
1034     paintInfo.context->save();
1035
1036     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
1037                              r.y() + o->style()->borderTopWidth(),
1038                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
1039                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
1040     // Draw the gradients to give the styled popup menu a button appearance
1041     paintMenuListButtonGradients(o, paintInfo, bounds);
1042
1043     // Since we actually know the size of the control here, we restrict the font scale to make sure the arrows will fit vertically in the bounds
1044     float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
1045     float centerY = bounds.y() + bounds.height() / 2.0f;
1046     float arrowHeight = baseArrowHeight * fontScale;
1047     float arrowWidth = baseArrowWidth * fontScale;
1048     float leftEdge = bounds.right() - arrowPaddingRight - arrowWidth;
1049     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
1050
1051     if (bounds.width() < arrowWidth + arrowPaddingLeft)
1052         return false;
1053     
1054     paintInfo.context->setFillColor(o->style()->color());
1055     paintInfo.context->setStrokeStyle(NoStroke);
1056
1057     FloatPoint arrow1[3];
1058     arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
1059     arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
1060     arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
1061
1062     // Draw the top arrow
1063     paintInfo.context->drawConvexPolygon(3, arrow1, true);
1064
1065     FloatPoint arrow2[3];
1066     arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
1067     arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
1068     arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
1069
1070     // Draw the bottom arrow
1071     paintInfo.context->drawConvexPolygon(3, arrow2, true);
1072
1073     Color leftSeparatorColor(0, 0, 0, 40);
1074     Color rightSeparatorColor(255, 255, 255, 40);
1075
1076     // FIXME: Should the separator thickness and space be scaled up by fontScale?
1077     int separatorSpace = 2;
1078     int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft); // FIXME: Round?
1079
1080     // Draw the separator to the left of the arrows
1081     paintInfo.context->setStrokeThickness(1.0f);
1082     paintInfo.context->setStrokeStyle(SolidStroke);
1083     paintInfo.context->setStrokeColor(leftSeparatorColor);
1084     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
1085                                 IntPoint(leftEdgeOfSeparator, bounds.bottom()));
1086
1087     paintInfo.context->setStrokeColor(rightSeparatorColor);
1088     paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
1089                                 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.bottom()));
1090
1091     paintInfo.context->restore();
1092     return false;
1093 }
1094
1095 void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1096 {
1097     NSControlSize controlSize = controlSizeForFont(style);
1098
1099     style->resetBorder();
1100     style->resetPadding();
1101     
1102     // Height is locked to auto.
1103     style->setHeight(Length(Auto));
1104
1105     // White-space is locked to pre
1106     style->setWhiteSpace(PRE);
1107
1108     // Set the foreground color to black or gray when we have the aqua look.
1109     // Cast to RGB32 is to work around a compiler bug.
1110     style->setColor(e->isEnabled() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
1111
1112     // Set the button's vertical size.
1113     setButtonSize(style);
1114
1115     // 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
1116     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
1117     // system font for the control size instead.
1118     setFontFromControlSize(selector, style, controlSize);
1119
1120     style->setBoxShadow(0);
1121 }
1122
1123 int RenderThemeMac::popupInternalPaddingLeft(RenderStyle* style) const
1124 {
1125     if (style->appearance() == MenulistAppearance)
1126         return popupButtonPadding(controlSizeForFont(style))[leftPadding];
1127     if (style->appearance() == MenulistButtonAppearance)
1128         return styledPopupPaddingLeft;
1129     return 0;
1130 }
1131
1132 int RenderThemeMac::popupInternalPaddingRight(RenderStyle* style) const
1133 {
1134     if (style->appearance() == MenulistAppearance)
1135         return popupButtonPadding(controlSizeForFont(style))[rightPadding];
1136     if (style->appearance() == MenulistButtonAppearance) {
1137         float fontScale = style->fontSize() / baseFontSize;
1138         float arrowWidth = baseArrowWidth * fontScale;
1139         return static_cast<int>(ceilf(arrowWidth + arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator));
1140     }
1141     return 0;
1142 }
1143
1144 int RenderThemeMac::popupInternalPaddingTop(RenderStyle* style) const
1145 {
1146     if (style->appearance() == MenulistAppearance)
1147         return popupButtonPadding(controlSizeForFont(style))[topPadding];
1148     if (style->appearance() == MenulistButtonAppearance)
1149         return styledPopupPaddingTop;
1150     return 0;
1151 }
1152
1153 int RenderThemeMac::popupInternalPaddingBottom(RenderStyle* style) const
1154 {
1155     if (style->appearance() == MenulistAppearance)
1156         return popupButtonPadding(controlSizeForFont(style))[bottomPadding];
1157     if (style->appearance() == MenulistButtonAppearance)
1158         return styledPopupPaddingBottom;
1159     return 0;
1160 }
1161
1162 void RenderThemeMac::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1163 {
1164     float fontScale = style->fontSize() / baseFontSize;
1165
1166     style->resetPadding();
1167     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1168
1169     const int minHeight = 15;
1170     style->setMinHeight(Length(minHeight, Fixed));
1171     
1172     style->setLineHeight(RenderStyle::initialLineHeight());
1173 }
1174
1175 void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1176 {
1177     NSPopUpButtonCell* popupButton = this->popupButton();
1178
1179     // Set the control size based off the rectangle we're painting into.
1180     setControlSize(popupButton, popupButtonSizes(), r.size());
1181
1182     // Update the various states we respond to.
1183     updateCheckedState(popupButton, o);
1184     updateEnabledState(popupButton, o);
1185     updatePressedState(popupButton, o);
1186     updateFocusedState(popupButton, o);
1187 }
1188
1189 const IntSize* RenderThemeMac::menuListSizes() const
1190 {
1191     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1192     return sizes;
1193 }
1194
1195 int RenderThemeMac::minimumMenuListSize(RenderStyle* style) const
1196 {
1197     return sizeForSystemFont(style, menuListSizes()).width();
1198 }
1199
1200 const int trackWidth = 5;
1201 const int trackRadius = 2;
1202
1203 void RenderThemeMac::adjustSliderTrackStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1204 {
1205     style->setBoxShadow(0);
1206 }
1207
1208 bool RenderThemeMac::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1209 {
1210     IntRect bounds = r;
1211
1212     if (o->style()->appearance() ==  SliderHorizontalAppearance || o->style()->appearance() ==  MediaSliderAppearance) {
1213         bounds.setHeight(trackWidth);
1214         bounds.setY(r.y() + r.height() / 2 - trackWidth / 2);
1215     } else if (o->style()->appearance() == SliderVerticalAppearance) {
1216         bounds.setWidth(trackWidth);
1217         bounds.setX(r.x() + r.width() / 2 - trackWidth / 2);
1218     }
1219
1220     LocalCurrentGraphicsContext localContext(paintInfo.context);
1221     CGContextRef context = paintInfo.context->platformContext();
1222     RetainPtr<CGColorSpaceRef> cspace(AdoptCF, CGColorSpaceCreateDeviceRGB());
1223
1224     paintInfo.context->save();
1225     CGContextClipToRect(context, bounds);
1226
1227     struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL };
1228     RetainPtr<CGFunctionRef> mainFunction(AdoptCF, CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks));
1229     RetainPtr<CGShadingRef> mainShading;
1230     if (o->style()->appearance() == SliderVerticalAppearance)
1231         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.bottom()), CGPointMake(bounds.right(), bounds.bottom()), mainFunction.get(), false, false));
1232     else
1233         mainShading.adoptCF(CGShadingCreateAxial(cspace.get(), CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.bottom()), mainFunction.get(), false, false));
1234
1235     IntSize radius(trackRadius, trackRadius);
1236     paintInfo.context->addRoundedRectClip(bounds,
1237         radius, radius,
1238         radius, radius);
1239     CGContextDrawShading(context, mainShading.get());
1240     paintInfo.context->restore();
1241     
1242     return false;
1243 }
1244
1245 void RenderThemeMac::adjustSliderThumbStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1246 {
1247     style->setBoxShadow(0);
1248 }
1249
1250 const float verticalSliderHeightPadding = 0.1f;
1251
1252 bool RenderThemeMac::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1253 {
1254     ASSERT(o->parent()->isSlider());
1255
1256     NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalAppearance
1257         ? sliderThumbVertical()
1258         : sliderThumbHorizontal();
1259
1260     LocalCurrentGraphicsContext localContext(paintInfo.context);
1261
1262     // Update the various states we respond to.
1263     updateEnabledState(sliderThumbCell, o->parent());
1264     updateFocusedState(sliderThumbCell, o->parent());
1265
1266     // Update the pressed state using the NSCell tracking methods, since that's how NSSliderCell keeps track of it.
1267     bool oldPressed;
1268     if (o->style()->appearance() == SliderThumbVerticalAppearance)
1269         oldPressed = m_isSliderThumbVerticalPressed;
1270     else
1271         oldPressed = m_isSliderThumbHorizontalPressed;
1272
1273     bool pressed = static_cast<RenderSlider*>(o->parent())->inDragMode();
1274
1275     if (o->style()->appearance() == SliderThumbVerticalAppearance)
1276         m_isSliderThumbVerticalPressed = pressed;
1277     else
1278         m_isSliderThumbHorizontalPressed = pressed;
1279
1280     if (pressed != oldPressed) {
1281         if (pressed)
1282             [sliderThumbCell startTrackingAt:NSPoint() inView:nil];
1283         else
1284             [sliderThumbCell stopTracking:NSPoint() at:NSPoint() inView:nil mouseIsUp:YES];
1285     }
1286
1287     FloatRect bounds = r;
1288     // Make the height of the vertical slider slightly larger so NSSliderCell will draw a vertical slider.
1289     if (o->style()->appearance() == SliderThumbVerticalAppearance)
1290         bounds.setHeight(bounds.height() + verticalSliderHeightPadding);
1291
1292     [sliderThumbCell drawWithFrame:NSRect(bounds) inView:o->view()->frameView()->getDocumentView()];
1293     [sliderThumbCell setControlView:nil];
1294
1295     return false;
1296 }
1297
1298 const int sliderThumbWidth = 15;
1299 const int sliderThumbHeight = 15;
1300 const int mediaSliderThumbWidth = 13;
1301 const int mediaSliderThumbHeight = 14;
1302
1303 void RenderThemeMac::adjustSliderThumbSize(RenderObject* o) const
1304 {
1305     if (o->style()->appearance() == SliderThumbHorizontalAppearance || o->style()->appearance() == SliderThumbVerticalAppearance) {
1306         o->style()->setWidth(Length(sliderThumbWidth, Fixed));
1307         o->style()->setHeight(Length(sliderThumbHeight, Fixed));
1308     } else if (o->style()->appearance() == MediaSliderThumbAppearance) {
1309         o->style()->setWidth(Length(mediaSliderThumbWidth, Fixed));
1310         o->style()->setHeight(Length(mediaSliderThumbHeight, Fixed));
1311     }
1312 }
1313
1314 bool RenderThemeMac::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1315 {
1316     NSSearchFieldCell* search = this->search();
1317     LocalCurrentGraphicsContext localContext(paintInfo.context);
1318
1319     setSearchCellState(o, r);
1320
1321     // Set the search button to nil before drawing.  Then reset it so we can draw it later.
1322     [search setSearchButtonCell:nil];
1323
1324     [search drawWithFrame:NSRect(r) inView:o->view()->frameView()->getDocumentView()];
1325 #ifdef BUILDING_ON_TIGER
1326     if ([search showsFirstResponder])
1327         wkDrawTextFieldCellFocusRing(search, NSRect(r));
1328 #endif
1329
1330     [search setControlView:nil];
1331     [search resetSearchButtonCell];
1332
1333     return false;
1334 }
1335
1336 void RenderThemeMac::setSearchCellState(RenderObject* o, const IntRect& r)
1337 {
1338     NSSearchFieldCell* search = this->search();
1339
1340     [search setControlSize:controlSizeForFont(o->style())];
1341
1342     // Update the various states we respond to.
1343     updateEnabledState(search, o);
1344     updateFocusedState(search, o);
1345 }
1346
1347 const IntSize* RenderThemeMac::searchFieldSizes() const
1348 {
1349     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
1350     return sizes;
1351 }
1352
1353 void RenderThemeMac::setSearchFieldSize(RenderStyle* style) const
1354 {
1355     // If the width and height are both specified, then we have nothing to do.
1356     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1357         return;
1358     
1359     // Use the font size to determine the intrinsic width of the control.
1360     setSizeFromFont(style, searchFieldSizes());
1361 }
1362
1363 void RenderThemeMac::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1364 {
1365     // Override border.
1366     style->resetBorder();
1367     const short borderWidth = 2;
1368     style->setBorderLeftWidth(borderWidth);
1369     style->setBorderLeftStyle(INSET);
1370     style->setBorderRightWidth(borderWidth);
1371     style->setBorderRightStyle(INSET);
1372     style->setBorderBottomWidth(borderWidth);
1373     style->setBorderBottomStyle(INSET);
1374     style->setBorderTopWidth(borderWidth);
1375     style->setBorderTopStyle(INSET);    
1376     
1377     // Override height.
1378     style->setHeight(Length(Auto));
1379     setSearchFieldSize(style);
1380     
1381     // Override padding size to match AppKit text positioning.
1382     const int padding = 1;
1383     style->setPaddingLeft(Length(padding, Fixed));
1384     style->setPaddingRight(Length(padding, Fixed));
1385     style->setPaddingTop(Length(padding, Fixed));
1386     style->setPaddingBottom(Length(padding, Fixed));
1387     
1388     NSControlSize controlSize = controlSizeForFont(style);
1389     setFontFromControlSize(selector, style, controlSize);
1390
1391     style->setBoxShadow(0);
1392 }
1393
1394 bool RenderThemeMac::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1395 {
1396     Node* input = o->node()->shadowAncestorNode();
1397     setSearchCellState(input->renderer(), r);
1398
1399     NSSearchFieldCell* search = this->search();
1400
1401     updatePressedState([search cancelButtonCell], o);
1402
1403     NSRect bounds = [search cancelButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
1404     [[search cancelButtonCell] drawWithFrame:bounds inView:o->view()->frameView()->getDocumentView()];
1405     [[search cancelButtonCell] setControlView:nil];
1406
1407     return false;
1408 }
1409
1410 const IntSize* RenderThemeMac::cancelButtonSizes() const
1411 {
1412     static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
1413     return sizes;
1414 }
1415
1416 void RenderThemeMac::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1417 {
1418     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1419     style->setWidth(Length(size.width(), Fixed));
1420     style->setHeight(Length(size.height(), Fixed));
1421     style->setBoxShadow(0);
1422 }
1423
1424 const IntSize* RenderThemeMac::resultsButtonSizes() const
1425 {
1426     static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
1427     return sizes;
1428 }
1429
1430 const int emptyResultsOffset = 9;
1431 void RenderThemeMac::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1432 {
1433     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1434     style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
1435     style->setHeight(Length(size.height(), Fixed));
1436     style->setBoxShadow(0);
1437 }
1438
1439 bool RenderThemeMac::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1440 {
1441     return false;
1442 }
1443
1444 void RenderThemeMac::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1445 {
1446     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1447     style->setWidth(Length(size.width(), Fixed));
1448     style->setHeight(Length(size.height(), Fixed));
1449     style->setBoxShadow(0);
1450 }
1451
1452 bool RenderThemeMac::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1453 {
1454     Node* input = o->node()->shadowAncestorNode();
1455     setSearchCellState(input->renderer(), r);
1456
1457     NSSearchFieldCell* search = this->search();
1458
1459     if ([search searchMenuTemplate] != nil)
1460         [search setSearchMenuTemplate:nil];
1461
1462     NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
1463     [[search searchButtonCell] drawWithFrame:bounds inView:o->view()->frameView()->getDocumentView()];
1464     [[search searchButtonCell] setControlView:nil];
1465     return false;
1466 }
1467
1468 const int resultsArrowWidth = 5;
1469 void RenderThemeMac::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
1470 {
1471     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1472     style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
1473     style->setHeight(Length(size.height(), Fixed));
1474     style->setBoxShadow(0);
1475 }
1476
1477 bool RenderThemeMac::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1478 {
1479     Node* input = o->node()->shadowAncestorNode();
1480     setSearchCellState(input->renderer(), r);
1481
1482     NSSearchFieldCell* search = this->search();
1483
1484     if (![search searchMenuTemplate])
1485         [search setSearchMenuTemplate:searchMenuTemplate()];
1486
1487     NSRect bounds = [search searchButtonRectForBounds:NSRect(input->renderer()->absoluteBoundingBoxRect())];
1488     [[search searchButtonCell] drawWithFrame:bounds inView:o->view()->frameView()->getDocumentView()];
1489     [[search searchButtonCell] setControlView:nil];
1490     return false;
1491 }
1492
1493 bool RenderThemeMac::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1494 {
1495     Node* node = o->element();
1496     if (!node)
1497         return false;
1498
1499     LocalCurrentGraphicsContext localContext(paintInfo.context);
1500     wkDrawMediaFullscreenButton(paintInfo.context->platformContext(), r, node->active());
1501     return false;
1502 }
1503
1504 bool RenderThemeMac::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1505 {
1506     Node* node = o->element();
1507     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1508     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1509         return false;
1510
1511     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1512     if (!mediaElement)
1513         return false;
1514     
1515     LocalCurrentGraphicsContext localContext(paintInfo.context);
1516     if (mediaElement->muted())
1517         wkDrawMediaUnMuteButton(paintInfo.context->platformContext(), r, node->active());
1518     else
1519         wkDrawMediaMuteButton(paintInfo.context->platformContext(), r, node->active());        
1520     return false;
1521 }
1522
1523 bool RenderThemeMac::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1524 {
1525     Node* node = o->element();
1526     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1527     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1528         return false;
1529
1530     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1531     if (!mediaElement)
1532         return false;
1533
1534     LocalCurrentGraphicsContext localContext(paintInfo.context);
1535     if (mediaElement->canPlay())
1536         wkDrawMediaPlayButton(paintInfo.context->platformContext(), r, node->active());
1537     else
1538         wkDrawMediaPauseButton(paintInfo.context->platformContext(), r, node->active());        
1539     return false;
1540 }
1541
1542 bool RenderThemeMac::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1543 {
1544     Node* node = o->element();
1545     if (!node)
1546         return false;
1547
1548     LocalCurrentGraphicsContext localContext(paintInfo.context);
1549     wkDrawMediaSeekBackButton(paintInfo.context->platformContext(), r, node->active());
1550     return false;
1551 }
1552
1553 bool RenderThemeMac::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1554 {
1555     Node* node = o->element();
1556     if (!node)
1557         return false;
1558
1559     LocalCurrentGraphicsContext localContext(paintInfo.context);
1560     wkDrawMediaSeekForwardButton(paintInfo.context->platformContext(), r, node->active());
1561     return false;
1562 }
1563
1564 bool RenderThemeMac::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1565 {
1566     Node* node = o->element();
1567     Node* mediaNode = node ? node->shadowAncestorNode() : 0;
1568     if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag)))
1569         return false;
1570
1571     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1572     if (!mediaElement)
1573         return false;
1574
1575     float percentLoaded = 0;
1576     if (MediaPlayer* player = mediaElement->player())
1577         if (player->duration())
1578             percentLoaded = player->maxTimeBuffered() / player->duration();
1579
1580     wkDrawMediaSliderTrack(paintInfo.context->platformContext(), r, percentLoaded);
1581     return false;
1582 }
1583
1584 bool RenderThemeMac::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r)
1585 {
1586     Node* node = o->element();
1587     if (!node)
1588         return false;
1589
1590     LocalCurrentGraphicsContext localContext(paintInfo.context);
1591     wkDrawMediaSliderThumb(paintInfo.context->platformContext(), r, node->active());
1592     return false;
1593 }
1594
1595 NSButtonCell* RenderThemeMac::checkbox() const
1596 {
1597     if (!m_checkbox) {
1598         m_checkbox.adoptNS([[NSButtonCell alloc] init]);
1599         [m_checkbox.get() setButtonType:NSSwitchButton];
1600         [m_checkbox.get() setTitle:nil];
1601         [m_checkbox.get() setAllowsMixedState:YES];
1602         [m_checkbox.get() setFocusRingType:NSFocusRingTypeExterior];
1603     }
1604     
1605     return m_checkbox.get();
1606 }
1607
1608 NSButtonCell* RenderThemeMac::radio() const
1609 {
1610     if (!m_radio) {
1611         m_radio.adoptNS([[NSButtonCell alloc] init]);
1612         [m_radio.get() setButtonType:NSRadioButton];
1613         [m_radio.get() setTitle:nil];
1614         [m_radio.get() setFocusRingType:NSFocusRingTypeExterior];
1615     }
1616     
1617     return m_radio.get();
1618 }
1619
1620 NSButtonCell* RenderThemeMac::button() const
1621 {
1622     if (!m_button) {
1623         m_button.adoptNS([[NSButtonCell alloc] init]);
1624         [m_button.get() setTitle:nil];
1625         [m_button.get() setButtonType:NSMomentaryPushInButton];
1626     }
1627     
1628     return m_button.get();
1629 }
1630
1631 NSPopUpButtonCell* RenderThemeMac::popupButton() const
1632 {
1633     if (!m_popupButton) {
1634         m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
1635         [m_popupButton.get() setUsesItemFromMenu:NO];
1636         [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
1637     }
1638     
1639     return m_popupButton.get();
1640 }
1641
1642 NSSearchFieldCell* RenderThemeMac::search() const
1643 {
1644     if (!m_search) {
1645         m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
1646         [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
1647         [m_search.get() setBezeled:YES];
1648         [m_search.get() setEditable:YES];
1649         [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
1650     }
1651
1652     return m_search.get();
1653 }
1654
1655 NSMenu* RenderThemeMac::searchMenuTemplate() const
1656 {
1657     if (!m_searchMenuTemplate)
1658         m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
1659
1660     return m_searchMenuTemplate.get();
1661 }
1662
1663 NSSliderCell* RenderThemeMac::sliderThumbHorizontal() const
1664 {
1665     if (!m_sliderThumbHorizontal) {
1666         m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
1667         [m_sliderThumbHorizontal.get() setTitle:nil];
1668         [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
1669         [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
1670         [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
1671     }
1672     
1673     return m_sliderThumbHorizontal.get();
1674 }
1675
1676 NSSliderCell* RenderThemeMac::sliderThumbVertical() const
1677 {
1678     if (!m_sliderThumbVertical) {
1679         m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
1680         [m_sliderThumbVertical.get() setTitle:nil];
1681         [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
1682         [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
1683         [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
1684     }
1685     
1686     return m_sliderThumbVertical.get();
1687 }
1688
1689 Image* RenderThemeMac::resizeCornerImage() const
1690 {
1691     if (!m_resizeCornerImage)
1692         m_resizeCornerImage = Image::loadPlatformResource("textAreaResizeCorner");
1693     return m_resizeCornerImage;
1694 }
1695
1696 } // namespace WebCore