Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / RenderThemeChromiumMac.mm
1 /*
2  * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2008, 2009 Google, Inc.
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 #import "config.h"
22 #import "core/rendering/RenderThemeChromiumMac.h"
23
24 #import "core/CSSValueKeywords.h"
25 #import "core/HTMLNames.h"
26 #import "core/UserAgentStyleSheets.h"
27 #import "core/css/CSSValueList.h"
28 #import "core/dom/Document.h"
29 #import "core/dom/Element.h"
30 #import "core/fileapi/FileList.h"
31 #import "core/html/HTMLInputElement.h"
32 #import "core/html/HTMLMediaElement.h"
33 #import "core/html/HTMLMeterElement.h"
34 #import "core/html/TimeRanges.h"
35 #import "core/html/shadow/MediaControlElements.h"
36 #import "core/frame/FrameView.h"
37 #import "core/rendering/PaintInfo.h"
38 #import "core/rendering/RenderLayer.h"
39 #import "core/rendering/RenderMedia.h"
40 #import "core/rendering/RenderMediaControls.h"
41 #import "core/rendering/RenderMeter.h"
42 #import "core/rendering/RenderProgress.h"
43 #import "core/rendering/RenderSlider.h"
44 #import "core/rendering/RenderView.h"
45 #import "core/rendering/style/ShadowList.h"
46 #import "platform/LayoutTestSupport.h"
47 #import "platform/SharedBuffer.h"
48 #import "platform/graphics/BitmapImage.h"
49 #import "platform/graphics/GraphicsContextStateSaver.h"
50 #import "platform/graphics/Image.h"
51 #import "platform/graphics/ImageBuffer.h"
52 #import "platform/mac/ColorMac.h"
53 #import "platform/mac/LocalCurrentGraphicsContext.h"
54 #import "platform/mac/ThemeMac.h"
55 #import "platform/mac/WebCoreNSCellExtras.h"
56 #import "platform/text/PlatformLocale.h"
57 #import "platform/text/StringTruncator.h"
58
59 #import <AvailabilityMacros.h>
60 #import <Carbon/Carbon.h>
61 #import <Cocoa/Cocoa.h>
62 #import <math.h>
63 #import <wtf/RetainPtr.h>
64 #import <wtf/StdLibExtras.h>
65
66 // The methods in this file are specific to the Mac OS X platform.
67
68 // We estimate the animation rate of a Mac OS X progress bar is 33 fps.
69 // Hard code the value here because we haven't found API for it.
70 const double progressAnimationFrameRate = 0.033;
71
72 // Mac OS X progress bar animation seems to have 256 frames.
73 const double progressAnimationNumFrames = 256;
74
75 @interface WebCoreRenderThemeNotificationObserver : NSObject
76 {
77     blink::RenderTheme *_theme;
78 }
79
80 - (id)initWithTheme:(blink::RenderTheme *)theme;
81 - (void)systemColorsDidChange:(NSNotification *)notification;
82
83 @end
84
85 @implementation WebCoreRenderThemeNotificationObserver
86
87 - (id)initWithTheme:(blink::RenderTheme *)theme
88 {
89     if (!(self = [super init]))
90         return nil;
91
92     _theme = theme;
93     return self;
94 }
95
96 - (void)systemColorsDidChange:(NSNotification *)unusedNotification
97 {
98     ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
99     _theme->platformColorsDidChange();
100 }
101
102 @end
103
104 @interface NSTextFieldCell (WKDetails)
105 - (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
106 @end
107
108
109 @interface WebCoreTextFieldCell : NSTextFieldCell
110 - (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
111 @end
112
113 @implementation WebCoreTextFieldCell
114 - (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus
115 {
116     // FIXME: This is a post-Lion-only workaround for <rdar://problem/11385461>. When that bug is resolved, we should remove this code.
117     CFMutableDictionaryRef coreUIDrawOptions = CFDictionaryCreateMutableCopy(NULL, 0, [super _coreUIDrawOptionsWithFrame:cellFrame inView:controlView includeFocus:includeFocus]);
118     CFDictionarySetValue(coreUIDrawOptions, @"borders only", kCFBooleanTrue);
119     return (CFDictionaryRef)[NSMakeCollectable(coreUIDrawOptions) autorelease];
120 }
121 @end
122
123 @interface RTCMFlippedView : NSView
124 {}
125
126 - (BOOL)isFlipped;
127 - (NSText *)currentEditor;
128
129 @end
130
131 @implementation RTCMFlippedView
132
133 - (BOOL)isFlipped {
134     return [[NSGraphicsContext currentContext] isFlipped];
135 }
136
137 - (NSText *)currentEditor {
138     return nil;
139 }
140
141 @end
142
143 // Forward declare Mac SPIs.
144 extern "C" {
145 void _NSDrawCarbonThemeBezel(NSRect frame, BOOL enabled, BOOL flipped);
146 // Request for public API: rdar://13787640
147 void _NSDrawCarbonThemeListBox(NSRect frame, BOOL enabled, BOOL flipped, BOOL always_yes);
148 }
149
150 namespace blink {
151
152 using namespace HTMLNames;
153
154 enum {
155     topMargin,
156     rightMargin,
157     bottomMargin,
158     leftMargin
159 };
160
161 enum {
162     topPadding,
163     rightPadding,
164     bottomPadding,
165     leftPadding
166 };
167
168 RenderThemeChromiumMac::RenderThemeChromiumMac()
169     : m_notificationObserver(AdoptNS, [[WebCoreRenderThemeNotificationObserver alloc] initWithTheme:this])
170 {
171     [[NSNotificationCenter defaultCenter] addObserver:m_notificationObserver.get()
172                                                         selector:@selector(systemColorsDidChange:)
173                                                             name:NSSystemColorsDidChangeNotification
174                                                           object:nil];
175 }
176
177 RenderThemeChromiumMac::~RenderThemeChromiumMac()
178 {
179     [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
180 }
181
182 Color RenderThemeChromiumMac::platformActiveSelectionBackgroundColor() const
183 {
184     NSColor* color = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
185     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
186 }
187
188 Color RenderThemeChromiumMac::platformInactiveSelectionBackgroundColor() const
189 {
190     NSColor* color = [[NSColor secondarySelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
191     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
192 }
193
194 Color RenderThemeChromiumMac::platformActiveSelectionForegroundColor() const
195 {
196     return Color::black;
197 }
198
199 Color RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() const
200 {
201     NSColor* color = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
202     return Color(static_cast<int>(255.0 * [color redComponent]), static_cast<int>(255.0 * [color greenComponent]), static_cast<int>(255.0 * [color blueComponent]));
203 }
204
205 Color RenderThemeChromiumMac::platformActiveListBoxSelectionForegroundColor() const
206 {
207     return Color::white;
208 }
209
210 Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor() const
211 {
212     return Color::black;
213 }
214
215 Color RenderThemeChromiumMac::platformFocusRingColor() const
216 {
217     static const RGBA32 oldAquaFocusRingColor = 0xFF7DADD9;
218     if (usesTestModeFocusRingColor())
219         return oldAquaFocusRingColor;
220
221     return systemColor(CSSValueWebkitFocusRingColor);
222 }
223
224 Color RenderThemeChromiumMac::platformInactiveListBoxSelectionBackgroundColor() const
225 {
226     return platformInactiveSelectionBackgroundColor();
227 }
228
229 static FontWeight toFontWeight(NSInteger appKitFontWeight)
230 {
231     ASSERT(appKitFontWeight > 0 && appKitFontWeight < 15);
232     if (appKitFontWeight > 14)
233         appKitFontWeight = 14;
234     else if (appKitFontWeight < 1)
235         appKitFontWeight = 1;
236
237     static FontWeight fontWeights[] = {
238         FontWeight100,
239         FontWeight100,
240         FontWeight200,
241         FontWeight300,
242         FontWeight400,
243         FontWeight500,
244         FontWeight600,
245         FontWeight600,
246         FontWeight700,
247         FontWeight800,
248         FontWeight800,
249         FontWeight900,
250         FontWeight900,
251         FontWeight900
252     };
253     return fontWeights[appKitFontWeight - 1];
254 }
255
256 void RenderThemeChromiumMac::systemFont(CSSValueID cssValueId, FontDescription& fontDescription) const
257 {
258     DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
259     DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
260     DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
261     DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
262     DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
263     DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
264     DEFINE_STATIC_LOCAL(FontDescription, controlFont, ());
265
266     FontDescription* cachedDesc;
267     NSFont* font = nil;
268     switch (cssValueId) {
269         case CSSValueSmallCaption:
270             cachedDesc = &smallSystemFont;
271             if (!smallSystemFont.isAbsoluteSize())
272                 font = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
273             break;
274         case CSSValueMenu:
275             cachedDesc = &menuFont;
276             if (!menuFont.isAbsoluteSize())
277                 font = [NSFont menuFontOfSize:[NSFont systemFontSize]];
278             break;
279         case CSSValueStatusBar:
280             cachedDesc = &labelFont;
281             if (!labelFont.isAbsoluteSize())
282                 font = [NSFont labelFontOfSize:[NSFont labelFontSize]];
283             break;
284         case CSSValueWebkitMiniControl:
285             cachedDesc = &miniControlFont;
286             if (!miniControlFont.isAbsoluteSize())
287                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
288             break;
289         case CSSValueWebkitSmallControl:
290             cachedDesc = &smallControlFont;
291             if (!smallControlFont.isAbsoluteSize())
292                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
293             break;
294         case CSSValueWebkitControl:
295             cachedDesc = &controlFont;
296             if (!controlFont.isAbsoluteSize())
297                 font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
298             break;
299         default:
300             cachedDesc = &systemFont;
301             if (!systemFont.isAbsoluteSize())
302                 font = [NSFont systemFontOfSize:[NSFont systemFontSize]];
303     }
304
305     if (font) {
306         NSFontManager *fontManager = [NSFontManager sharedFontManager];
307         cachedDesc->setIsAbsoluteSize(true);
308         cachedDesc->setGenericFamily(FontDescription::NoFamily);
309         cachedDesc->firstFamily().setFamily([font webCoreFamilyName]);
310         cachedDesc->setSpecifiedSize([font pointSize]);
311         cachedDesc->setWeight(toFontWeight([fontManager weightOfFont:font]));
312         cachedDesc->setStyle([fontManager traitsOfFont:font] & NSItalicFontMask ? FontStyleItalic : FontStyleNormal);
313     }
314     fontDescription = *cachedDesc;
315 }
316
317 static RGBA32 convertNSColorToColor(NSColor *color)
318 {
319     NSColor *colorInColorSpace = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
320     if (colorInColorSpace) {
321         static const double scaleFactor = nextafter(256.0, 0.0);
322         return makeRGB(static_cast<int>(scaleFactor * [colorInColorSpace redComponent]),
323             static_cast<int>(scaleFactor * [colorInColorSpace greenComponent]),
324             static_cast<int>(scaleFactor * [colorInColorSpace blueComponent]));
325     }
326
327     // This conversion above can fail if the NSColor in question is an NSPatternColor
328     // (as many system colors are). These colors are actually a repeating pattern
329     // not just a solid color. To work around this we simply draw a 1x1 image of
330     // the color and use that pixel's color. It might be better to use an average of
331     // the colors in the pattern instead.
332     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
333                                                                              pixelsWide:1
334                                                                              pixelsHigh:1
335                                                                           bitsPerSample:8
336                                                                         samplesPerPixel:4
337                                                                                hasAlpha:YES
338                                                                                isPlanar:NO
339                                                                          colorSpaceName:NSDeviceRGBColorSpace
340                                                                             bytesPerRow:4
341                                                                            bitsPerPixel:32];
342
343     [NSGraphicsContext saveGraphicsState];
344     [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep]];
345     NSEraseRect(NSMakeRect(0, 0, 1, 1));
346     [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
347     [NSGraphicsContext restoreGraphicsState];
348
349     NSUInteger pixel[4];
350     [offscreenRep getPixel:pixel atX:0 y:0];
351
352     [offscreenRep release];
353
354     return makeRGB(pixel[0], pixel[1], pixel[2]);
355 }
356
357 static RGBA32 menuBackgroundColor()
358 {
359     NSBitmapImageRep *offscreenRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil
360                                                                              pixelsWide:1
361                                                                              pixelsHigh:1
362                                                                           bitsPerSample:8
363                                                                         samplesPerPixel:4
364                                                                                hasAlpha:YES
365                                                                                isPlanar:NO
366                                                                          colorSpaceName:NSDeviceRGBColorSpace
367                                                                             bytesPerRow:4
368                                                                            bitsPerPixel:32];
369
370     CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep] graphicsPort]);
371     CGRect rect = CGRectMake(0, 0, 1, 1);
372     HIThemeMenuDrawInfo drawInfo;
373     drawInfo.version =  0;
374     drawInfo.menuType = kThemeMenuTypePopUp;
375     HIThemeDrawMenuBackground(&rect, &drawInfo, context, kHIThemeOrientationInverted);
376
377     NSUInteger pixel[4];
378     [offscreenRep getPixel:pixel atX:0 y:0];
379
380     [offscreenRep release];
381
382     return makeRGB(pixel[0], pixel[1], pixel[2]);
383 }
384
385 void RenderThemeChromiumMac::platformColorsDidChange()
386 {
387     m_systemColorCache.clear();
388     RenderTheme::platformColorsDidChange();
389 }
390
391 Color RenderThemeChromiumMac::systemColor(CSSValueID cssValueId) const
392 {
393     {
394         HashMap<int, RGBA32>::iterator it = m_systemColorCache.find(cssValueId);
395         if (it != m_systemColorCache.end())
396             return it->value;
397     }
398
399     Color color;
400     bool needsFallback = false;
401     switch (cssValueId) {
402         case CSSValueActiveborder:
403             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
404             break;
405         case CSSValueActivecaption:
406             color = convertNSColorToColor([NSColor windowFrameTextColor]);
407             break;
408         case CSSValueAppworkspace:
409             color = convertNSColorToColor([NSColor headerColor]);
410             break;
411         case CSSValueBackground:
412             // Use theme independent default
413             needsFallback = true;
414             break;
415         case CSSValueButtonface:
416             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
417             // We may want to change this to use the NSColor in future.
418             color = 0xFFC0C0C0;
419             break;
420         case CSSValueButtonhighlight:
421             color = convertNSColorToColor([NSColor controlHighlightColor]);
422             break;
423         case CSSValueButtonshadow:
424             color = convertNSColorToColor([NSColor controlShadowColor]);
425             break;
426         case CSSValueButtontext:
427             color = convertNSColorToColor([NSColor controlTextColor]);
428             break;
429         case CSSValueCaptiontext:
430             color = convertNSColorToColor([NSColor textColor]);
431             break;
432         case CSSValueGraytext:
433             color = convertNSColorToColor([NSColor disabledControlTextColor]);
434             break;
435         case CSSValueHighlight:
436             color = convertNSColorToColor([NSColor selectedTextBackgroundColor]);
437             break;
438         case CSSValueHighlighttext:
439             color = convertNSColorToColor([NSColor selectedTextColor]);
440             break;
441         case CSSValueInactiveborder:
442             color = convertNSColorToColor([NSColor controlBackgroundColor]);
443             break;
444         case CSSValueInactivecaption:
445             color = convertNSColorToColor([NSColor controlBackgroundColor]);
446             break;
447         case CSSValueInactivecaptiontext:
448             color = convertNSColorToColor([NSColor textColor]);
449             break;
450         case CSSValueInfobackground:
451             // There is no corresponding NSColor for this so we use a hard coded value.
452             color = 0xFFFBFCC5;
453             break;
454         case CSSValueInfotext:
455             color = convertNSColorToColor([NSColor textColor]);
456             break;
457         case CSSValueMenu:
458             color = menuBackgroundColor();
459             break;
460         case CSSValueMenutext:
461             color = convertNSColorToColor([NSColor selectedMenuItemTextColor]);
462             break;
463         case CSSValueScrollbar:
464             color = convertNSColorToColor([NSColor scrollBarColor]);
465             break;
466         case CSSValueText:
467             color = convertNSColorToColor([NSColor textColor]);
468             break;
469         case CSSValueThreeddarkshadow:
470             color = convertNSColorToColor([NSColor controlDarkShadowColor]);
471             break;
472         case CSSValueThreedshadow:
473             color = convertNSColorToColor([NSColor shadowColor]);
474             break;
475         case CSSValueThreedface:
476             // We use this value instead of NSColor's controlColor to avoid website incompatibilities.
477             // We may want to change this to use the NSColor in future.
478             color = 0xFFC0C0C0;
479             break;
480         case CSSValueThreedhighlight:
481             color = convertNSColorToColor([NSColor highlightColor]);
482             break;
483         case CSSValueThreedlightshadow:
484             color = convertNSColorToColor([NSColor controlLightHighlightColor]);
485             break;
486         case CSSValueWebkitFocusRingColor:
487             color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
488             break;
489         case CSSValueWindow:
490             color = convertNSColorToColor([NSColor windowBackgroundColor]);
491             break;
492         case CSSValueWindowframe:
493             color = convertNSColorToColor([NSColor windowFrameColor]);
494             break;
495         case CSSValueWindowtext:
496             color = convertNSColorToColor([NSColor windowFrameTextColor]);
497             break;
498         default:
499             needsFallback = true;
500             break;
501     }
502
503     if (needsFallback)
504         color = RenderTheme::systemColor(cssValueId);
505
506     m_systemColorCache.set(cssValueId, color.rgb());
507
508     return color;
509 }
510
511 bool RenderThemeChromiumMac::isControlStyled(const RenderStyle* style, const CachedUAStyle* uaStyle) const
512 {
513     ASSERT(uaStyle);
514     if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart)
515         return style->border() != uaStyle->border || style->boxShadow();
516
517     // FIXME: This is horrible, but there is not much else that can be done.  Menu lists cannot draw properly when
518     // scaled.  They can't really draw properly when transformed either.  We can't detect the transform case at style
519     // adjustment time so that will just have to stay broken.  We can however detect that we're zooming.  If zooming
520     // is in effect we treat it like the control is styled.
521     if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
522         return true;
523     // FIXME: NSSearchFieldCell doesn't work well when scaled.
524     if (style->appearance() == SearchFieldPart && style->effectiveZoom() != 1)
525         return true;
526
527     return RenderTheme::isControlStyled(style, uaStyle);
528 }
529
530 const int sliderThumbShadowBlur = 1;
531
532 void RenderThemeChromiumMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
533 {
534     ControlPart part = o->style()->appearance();
535
536 #if USE(NEW_THEME)
537     switch (part) {
538         case CheckboxPart:
539         case RadioPart:
540         case PushButtonPart:
541         case SquareButtonPart:
542         case ButtonPart:
543         case InnerSpinButtonPart:
544             return RenderTheme::adjustRepaintRect(o, r);
545         default:
546             break;
547     }
548 #endif
549
550     float zoomLevel = o->style()->effectiveZoom();
551
552     if (part == MenulistPart) {
553         setPopupButtonCellState(o, r);
554         IntSize size = popupButtonSizes()[[popupButton() controlSize]];
555         size.setHeight(size.height() * zoomLevel);
556         size.setWidth(r.width());
557         r = inflateRect(r, size, popupButtonMargins(), zoomLevel);
558     } else if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
559         r.setHeight(r.height() + sliderThumbShadowBlur);
560     }
561 }
562
563 IntRect RenderThemeChromiumMac::inflateRect(const IntRect& r, const IntSize& size, const int* margins, float zoomLevel) const
564 {
565     // Only do the inflation if the available width/height are too small.  Otherwise try to
566     // fit the glow/check space into the available box's width/height.
567     int widthDelta = r.width() - (size.width() + margins[leftMargin] * zoomLevel + margins[rightMargin] * zoomLevel);
568     int heightDelta = r.height() - (size.height() + margins[topMargin] * zoomLevel + margins[bottomMargin] * zoomLevel);
569     IntRect result(r);
570     if (widthDelta < 0) {
571         result.setX(result.x() - margins[leftMargin] * zoomLevel);
572         result.setWidth(result.width() - widthDelta);
573     }
574     if (heightDelta < 0) {
575         result.setY(result.y() - margins[topMargin] * zoomLevel);
576         result.setHeight(result.height() - heightDelta);
577     }
578     return result;
579 }
580
581 FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
582 {
583     FloatRect partRect(inputRect);
584
585     // Compute an offset between the part renderer and the input renderer
586     FloatSize offsetFromInputRenderer;
587     const RenderObject* renderer = partRenderer;
588     while (renderer && renderer != inputRenderer) {
589         RenderObject* containingRenderer = renderer->container();
590         offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint()));
591         renderer = containingRenderer;
592     }
593     // If the input renderer was not a container, something went wrong
594     ASSERT(renderer == inputRenderer);
595     // Move the rect into partRenderer's coords
596     partRect.move(offsetFromInputRenderer);
597     // Account for the local drawing offset (tx, ty)
598     partRect.move(r.x(), r.y());
599
600     return partRect;
601 }
602
603 void RenderThemeChromiumMac::updateCheckedState(NSCell* cell, const RenderObject* o)
604 {
605     bool oldIndeterminate = [cell state] == NSMixedState;
606     bool indeterminate = isIndeterminate(o);
607     bool checked = isChecked(o);
608
609     if (oldIndeterminate != indeterminate) {
610         [cell setState:indeterminate ? NSMixedState : (checked ? NSOnState : NSOffState)];
611         return;
612     }
613
614     bool oldChecked = [cell state] == NSOnState;
615     if (checked != oldChecked)
616         [cell setState:checked ? NSOnState : NSOffState];
617 }
618
619 void RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o)
620 {
621     bool oldEnabled = [cell isEnabled];
622     bool enabled = isEnabled(o);
623     if (enabled != oldEnabled)
624         [cell setEnabled:enabled];
625 }
626
627 void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o)
628 {
629     bool oldFocused = [cell showsFirstResponder];
630     bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
631     if (focused != oldFocused)
632         [cell setShowsFirstResponder:focused];
633 }
634
635 void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o)
636 {
637     bool oldPressed = [cell isHighlighted];
638     bool pressed = (o->node() && o->node()->active());
639     if (pressed != oldPressed)
640         [cell setHighlighted:pressed];
641 }
642
643 NSControlSize RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const
644 {
645     int fontSize = style->fontSize();
646     if (fontSize >= 16)
647         return NSRegularControlSize;
648     if (fontSize >= 11)
649         return NSSmallControlSize;
650     return NSMiniControlSize;
651 }
652
653 // We don't use controlSizeForFont() for search field decorations because it needs to fit
654 // into the search field. The font size will already be modified by
655 // setFontFromControlSize() called on the search field.
656 static NSControlSize searchFieldControlSizeForFont(RenderStyle* style)
657 {
658     int fontSize = style->fontSize();
659     if (fontSize >= 13)
660         return NSRegularControlSize;
661     if (fontSize >= 11)
662         return NSSmallControlSize;
663     return NSMiniControlSize;
664 }
665
666 void RenderThemeChromiumMac::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize, float zoomLevel)
667 {
668     NSControlSize size;
669     if (minSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomLevel) &&
670         minSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomLevel))
671         size = NSRegularControlSize;
672     else if (minSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomLevel) &&
673              minSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomLevel))
674         size = NSSmallControlSize;
675     else
676         size = NSMiniControlSize;
677     if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same.
678         [cell setControlSize:size];
679 }
680
681 IntSize RenderThemeChromiumMac::sizeForFont(RenderStyle* style, const IntSize* sizes) const
682 {
683     if (style->effectiveZoom() != 1.0f) {
684         IntSize result = sizes[controlSizeForFont(style)];
685         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
686     }
687     return sizes[controlSizeForFont(style)];
688 }
689
690 IntSize RenderThemeChromiumMac::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const
691 {
692     if (style->effectiveZoom() != 1.0f) {
693         IntSize result = sizes[controlSizeForSystemFont(style)];
694         return IntSize(result.width() * style->effectiveZoom(), result.height() * style->effectiveZoom());
695     }
696     return sizes[controlSizeForSystemFont(style)];
697 }
698
699 void RenderThemeChromiumMac::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const
700 {
701     // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
702     IntSize size = sizeForFont(style, sizes);
703     if (style->width().isIntrinsicOrAuto() && size.width() > 0)
704         style->setWidth(Length(size.width(), Fixed));
705     if (style->height().isAuto() && size.height() > 0)
706         style->setHeight(Length(size.height(), Fixed));
707 }
708
709 void RenderThemeChromiumMac::setFontFromControlSize(RenderStyle* style, NSControlSize controlSize) const
710 {
711     FontDescription fontDescription;
712     fontDescription.setIsAbsoluteSize(true);
713     fontDescription.setGenericFamily(FontDescription::SerifFamily);
714
715     NSFont* font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:controlSize]];
716     fontDescription.firstFamily().setFamily([font webCoreFamilyName]);
717     fontDescription.setComputedSize([font pointSize] * style->effectiveZoom());
718     fontDescription.setSpecifiedSize([font pointSize] * style->effectiveZoom());
719
720     // Reset line height
721     style->setLineHeight(RenderStyle::initialLineHeight());
722
723     if (style->setFontDescription(fontDescription))
724         style->font().update(nullptr);
725 }
726
727 NSControlSize RenderThemeChromiumMac::controlSizeForSystemFont(RenderStyle* style) const
728 {
729     float fontSize = style->fontSize();
730     float zoomLevel = style->effectiveZoom();
731     if (zoomLevel != 1)
732         fontSize /= zoomLevel;
733     if (fontSize >= [NSFont systemFontSizeForControlSize:NSRegularControlSize])
734         return NSRegularControlSize;
735     if (fontSize >= [NSFont systemFontSizeForControlSize:NSSmallControlSize])
736         return NSSmallControlSize;
737     return NSMiniControlSize;
738 }
739
740 bool RenderThemeChromiumMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
741 {
742     LocalCurrentGraphicsContext localContext(paintInfo.context);
743
744 #if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
745     bool useNSTextFieldCell = o->style()->hasAppearance()
746         && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
747         && !o->style()->hasBackgroundImage();
748
749     // We do not use NSTextFieldCell to draw styled text fields on Lion and SnowLeopard because
750     // there are a number of bugs on those platforms that require NSTextFieldCell to be in charge
751     // of painting its own background. We need WebCore to paint styled backgrounds, so we'll use
752     // this AppKit SPI function instead.
753     if (!useNSTextFieldCell) {
754         _NSDrawCarbonThemeBezel(r, isEnabled(o) && !isReadOnlyControl(o), YES);
755         return false;
756     }
757 #endif
758
759     NSTextFieldCell *textField = this->textField();
760
761     GraphicsContextStateSaver stateSaver(*paintInfo.context);
762
763     [textField setEnabled:(isEnabled(o) && !isReadOnlyControl(o))];
764     [textField drawWithFrame:NSRect(r) inView:documentViewFor(o)];
765
766     [textField setControlView:nil];
767
768     return false;
769 }
770
771 bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
772 {
773     // This draws the caps lock indicator as it was done by WKDrawCapsLockIndicator.
774     LocalCurrentGraphicsContext localContext(paintInfo.context);
775     CGContextRef c = localContext.cgContext();
776     CGMutablePathRef shape = CGPathCreateMutable();
777
778     // To draw the caps lock indicator, draw the shape into a small
779     // square that is then scaled to the size of r.
780     const CGFloat kSquareSize = 17;
781
782     // Create a rounted square shape.
783     CGPathMoveToPoint(shape, NULL, 16.5, 4.5);
784     CGPathAddArc(shape, NULL, 12.5, 12.5, 4, 0,        M_PI_2,   false);
785     CGPathAddArc(shape, NULL, 4.5,  12.5, 4, M_PI_2,   M_PI,     false);
786     CGPathAddArc(shape, NULL, 4.5,  4.5,  4, M_PI,     3*M_PI/2, false);
787     CGPathAddArc(shape, NULL, 12.5, 4.5,  4, 3*M_PI/2, 0,        false);
788
789     // Draw the arrow - note this is drawing in a flipped coordinate system, so the
790     // arrow is pointing down.
791     CGPathMoveToPoint(shape, NULL, 8.5, 2);  // Tip point.
792     CGPathAddLineToPoint(shape, NULL, 4,     7);
793     CGPathAddLineToPoint(shape, NULL, 6.25,  7);
794     CGPathAddLineToPoint(shape, NULL, 6.25,  10.25);
795     CGPathAddLineToPoint(shape, NULL, 10.75, 10.25);
796     CGPathAddLineToPoint(shape, NULL, 10.75, 7);
797     CGPathAddLineToPoint(shape, NULL, 13,    7);
798     CGPathAddLineToPoint(shape, NULL, 8.5,   2);
799
800     // Draw the rectangle that underneath (or above in the flipped system) the arrow.
801     CGPathAddLineToPoint(shape, NULL, 10.75, 12);
802     CGPathAddLineToPoint(shape, NULL, 6.25,  12);
803     CGPathAddLineToPoint(shape, NULL, 6.25,  14.25);
804     CGPathAddLineToPoint(shape, NULL, 10.75, 14.25);
805     CGPathAddLineToPoint(shape, NULL, 10.75, 12);
806
807     // Scale and translate the shape.
808     CGRect cgr = r;
809     CGFloat maxX = CGRectGetMaxX(cgr);
810     CGFloat minY = CGRectGetMinY(cgr);
811     CGFloat heightScale = r.height() / kSquareSize;
812     CGAffineTransform transform = CGAffineTransformMake(
813         heightScale, 0,  // A  B
814         0, heightScale,  // C  D
815         maxX - r.height(), minY);  // Tx Ty
816
817     CGMutablePathRef paintPath = CGPathCreateMutable();
818     CGPathAddPath(paintPath, &transform, shape);
819     CGPathRelease(shape);
820
821     CGContextSetRGBFillColor(c, 0, 0, 0, 0.4);
822     CGContextBeginPath(c);
823     CGContextAddPath(c, paintPath);
824     CGContextFillPath(c);
825     CGPathRelease(paintPath);
826
827     return false;
828 }
829
830 bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
831 {
832     LocalCurrentGraphicsContext localContext(paintInfo.context);
833     _NSDrawCarbonThemeListBox(r, isEnabled(o) && !isReadOnlyControl(o), YES, YES);
834     return false;
835 }
836
837 const int* RenderThemeChromiumMac::popupButtonMargins() const
838 {
839     static const int margins[3][4] =
840     {
841         { 0, 3, 1, 3 },
842         { 0, 3, 2, 3 },
843         { 0, 1, 0, 1 }
844     };
845     return margins[[popupButton() controlSize]];
846 }
847
848 const IntSize* RenderThemeChromiumMac::popupButtonSizes() const
849 {
850     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
851     return sizes;
852 }
853
854 const int* RenderThemeChromiumMac::popupButtonPadding(NSControlSize size) const
855 {
856     static const int padding[3][4] =
857     {
858         { 2, 26, 3, 8 },
859         { 2, 23, 3, 8 },
860         { 2, 22, 3, 10 }
861     };
862     return padding[size];
863 }
864
865 bool RenderThemeChromiumMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
866 {
867     LocalCurrentGraphicsContext localContext(paintInfo.context);
868     setPopupButtonCellState(o, r);
869
870     NSPopUpButtonCell* popupButton = this->popupButton();
871
872     float zoomLevel = o->style()->effectiveZoom();
873     IntSize size = popupButtonSizes()[[popupButton controlSize]];
874     size.setHeight(size.height() * zoomLevel);
875     size.setWidth(r.width());
876
877     // Now inflate it to account for the shadow.
878     IntRect inflatedRect = r;
879     if (r.width() >= minimumMenuListSize(o->style()))
880         inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(), zoomLevel);
881
882     GraphicsContextStateSaver stateSaver(*paintInfo.context);
883
884     // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
885     paintInfo.context->clip(inflatedRect);
886
887     if (zoomLevel != 1.0f) {
888         inflatedRect.setWidth(inflatedRect.width() / zoomLevel);
889         inflatedRect.setHeight(inflatedRect.height() / zoomLevel);
890         paintInfo.context->translate(inflatedRect.x(), inflatedRect.y());
891         paintInfo.context->scale(zoomLevel, zoomLevel);
892         paintInfo.context->translate(-inflatedRect.x(), -inflatedRect.y());
893     }
894
895     NSView *view = documentViewFor(o);
896     [popupButton drawWithFrame:inflatedRect inView:view];
897 #if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
898     if (isFocused(o) && o->style()->outlineStyleIsAuto())
899         [popupButton _web_drawFocusRingWithFrame:inflatedRect inView:view];
900 #endif
901     [popupButton setControlView:nil];
902
903     return false;
904 }
905
906 IntSize RenderThemeChromiumMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
907 {
908     if (NoControlPart == renderMeter->style()->appearance())
909         return bounds.size();
910
911     NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
912     // Makes enough room for cell's intrinsic size.
913     NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
914     return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
915                    bounds.height() < cellSize.height ? cellSize.height : bounds.height());
916 }
917
918 bool RenderThemeChromiumMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
919 {
920     if (!renderObject->isMeter())
921         return true;
922
923     LocalCurrentGraphicsContext localContext(paintInfo.context);
924
925     NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
926     GraphicsContextStateSaver stateSaver(*paintInfo.context);
927
928     [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
929     [cell setControlView:nil];
930     return false;
931 }
932
933 bool RenderThemeChromiumMac::supportsMeter(ControlPart part) const
934 {
935     switch (part) {
936     case RelevancyLevelIndicatorPart:
937     case DiscreteCapacityLevelIndicatorPart:
938     case RatingLevelIndicatorPart:
939     case MeterPart:
940     case ContinuousCapacityLevelIndicatorPart:
941         return true;
942     default:
943         return false;
944     }
945 }
946
947 NSLevelIndicatorStyle RenderThemeChromiumMac::levelIndicatorStyleFor(ControlPart part) const
948 {
949     switch (part) {
950     case RelevancyLevelIndicatorPart:
951         return NSRelevancyLevelIndicatorStyle;
952     case DiscreteCapacityLevelIndicatorPart:
953         return NSDiscreteCapacityLevelIndicatorStyle;
954     case RatingLevelIndicatorPart:
955         return NSRatingLevelIndicatorStyle;
956     case MeterPart:
957     case ContinuousCapacityLevelIndicatorPart:
958     default:
959         return NSContinuousCapacityLevelIndicatorStyle;
960     }
961
962 }
963
964 NSLevelIndicatorCell* RenderThemeChromiumMac::levelIndicatorFor(const RenderMeter* renderMeter) const
965 {
966     RenderStyle* style = renderMeter->style();
967     ASSERT(style->appearance() != NoControlPart);
968
969     if (!m_levelIndicator)
970         m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
971     NSLevelIndicatorCell* cell = m_levelIndicator.get();
972
973     HTMLMeterElement* element = renderMeter->meterElement();
974     double value = element->value();
975
976     // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
977     // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
978     switch (element->gaugeRegion()) {
979     case HTMLMeterElement::GaugeRegionOptimum:
980         // Make meter the green
981         [cell setWarningValue:value + 1];
982         [cell setCriticalValue:value + 2];
983         break;
984     case HTMLMeterElement::GaugeRegionSuboptimal:
985         // Make the meter yellow
986         [cell setWarningValue:value - 1];
987         [cell setCriticalValue:value + 1];
988         break;
989     case HTMLMeterElement::GaugeRegionEvenLessGood:
990         // Make the meter red
991         [cell setWarningValue:value - 2];
992         [cell setCriticalValue:value - 1];
993         break;
994     }
995
996     [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
997     [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
998     [cell setMinValue:element->min()];
999     [cell setMaxValue:element->max()];
1000     RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
1001     [cell setObjectValue:valueObject.get()];
1002
1003     return cell;
1004 }
1005
1006 const IntSize* RenderThemeChromiumMac::progressBarSizes() const
1007 {
1008     static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) };
1009     return sizes;
1010 }
1011
1012 const int* RenderThemeChromiumMac::progressBarMargins(NSControlSize controlSize) const
1013 {
1014     static const int margins[3][4] =
1015     {
1016         { 0, 0, 1, 0 },
1017         { 0, 0, 1, 0 },
1018         { 0, 0, 1, 0 },
1019     };
1020     return margins[controlSize];
1021 }
1022
1023 int RenderThemeChromiumMac::minimumProgressBarHeight(RenderStyle* style) const
1024 {
1025     return sizeForSystemFont(style, progressBarSizes()).height();
1026 }
1027
1028 double RenderThemeChromiumMac::animationRepeatIntervalForProgressBar(RenderProgress*) const
1029 {
1030     return progressAnimationFrameRate;
1031 }
1032
1033 double RenderThemeChromiumMac::animationDurationForProgressBar(RenderProgress*) const
1034 {
1035     return progressAnimationNumFrames * progressAnimationFrameRate;
1036 }
1037
1038 bool RenderThemeChromiumMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
1039 {
1040     if (!renderObject->isProgress())
1041         return true;
1042
1043     float zoomLevel = renderObject->style()->effectiveZoom();
1044     int controlSize = controlSizeForFont(renderObject->style());
1045     IntSize size = progressBarSizes()[controlSize];
1046     size.setHeight(size.height() * zoomLevel);
1047     size.setWidth(rect.width());
1048
1049     // Now inflate it to account for the shadow.
1050     IntRect inflatedRect = rect;
1051     if (rect.height() <= minimumProgressBarHeight(renderObject->style()))
1052         inflatedRect = inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel);
1053
1054     RenderProgress* renderProgress = toRenderProgress(renderObject);
1055     HIThemeTrackDrawInfo trackInfo;
1056     trackInfo.version = 0;
1057     if (controlSize == NSRegularControlSize)
1058         trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
1059     else
1060         trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar;
1061
1062     trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size());
1063     trackInfo.min = 0;
1064     trackInfo.max = std::numeric_limits<SInt32>::max();
1065     trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
1066     trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
1067     trackInfo.attributes = kThemeTrackHorizontal;
1068     trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
1069     trackInfo.reserved = 0;
1070     trackInfo.filler1 = 0;
1071
1072     OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size());
1073     if (!imageBuffer)
1074         return true;
1075
1076     ContextContainer cgContextContainer(imageBuffer->context());
1077     CGContextRef cgContext = cgContextContainer.context();
1078     HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
1079
1080     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1081
1082     if (!renderProgress->style()->isLeftToRightDirection()) {
1083         paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
1084         paintInfo.context->scale(-1, 1);
1085     }
1086
1087     paintInfo.context->drawImageBuffer(imageBuffer.get(),
1088         FloatRect(inflatedRect.location(), imageBuffer->size()));
1089     return false;
1090 }
1091
1092 const float baseFontSize = 11.0f;
1093 const float baseArrowHeight = 4.0f;
1094 const float baseArrowWidth = 5.0f;
1095 const float baseSpaceBetweenArrows = 2.0f;
1096 const int arrowPaddingLeft = 6;
1097 const int arrowPaddingRight = 6;
1098 const int paddingBeforeSeparator = 4;
1099 const int baseBorderRadius = 5;
1100 const int styledPopupPaddingLeft = 8;
1101 const int styledPopupPaddingTop = 1;
1102 const int styledPopupPaddingBottom = 2;
1103
1104 bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1105 {
1106     IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(),
1107                              r.y() + o->style()->borderTopWidth(),
1108                              r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(),
1109                              r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth());
1110     // 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
1111     float fontScale = std::min(o->style()->fontSize() / baseFontSize, bounds.height() / (baseArrowHeight * 2 + baseSpaceBetweenArrows));
1112     float centerY = bounds.y() + bounds.height() / 2.0f;
1113     float arrowHeight = baseArrowHeight * fontScale;
1114     float arrowWidth = baseArrowWidth * fontScale;
1115     float leftEdge = bounds.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
1116     float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
1117
1118     if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
1119         return false;
1120
1121     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1122
1123     paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor));
1124     paintInfo.context->setStrokeStyle(NoStroke);
1125
1126     FloatPoint arrow1[3];
1127     arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f);
1128     arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f);
1129     arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight);
1130
1131     // Draw the top arrow
1132     paintInfo.context->drawConvexPolygon(3, arrow1, true);
1133
1134     FloatPoint arrow2[3];
1135     arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f);
1136     arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f);
1137     arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight);
1138
1139     // Draw the bottom arrow
1140     paintInfo.context->drawConvexPolygon(3, arrow2, true);
1141     return false;
1142 }
1143
1144 static const IntSize* menuListButtonSizes()
1145 {
1146     static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
1147     return sizes;
1148 }
1149
1150 void RenderThemeChromiumMac::adjustMenuListStyle(RenderStyle* style, Element* e) const
1151 {
1152     NSControlSize controlSize = controlSizeForFont(style);
1153
1154     style->resetBorder();
1155     style->resetPadding();
1156
1157     // Height is locked to auto.
1158     style->setHeight(Length(Auto));
1159
1160     // White-space is locked to pre
1161     style->setWhiteSpace(PRE);
1162
1163     // Set the foreground color to black or gray when we have the aqua look.
1164     // Cast to RGB32 is to work around a compiler bug.
1165     style->setColor(e && !e->isDisabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray);
1166
1167     // Set the button's vertical size.
1168     setSizeFromFont(style, menuListButtonSizes());
1169
1170     // 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
1171     // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
1172     // system font for the control size instead.
1173     setFontFromControlSize(style, controlSize);
1174 }
1175
1176 const int autofillPopupHorizontalPadding = 4;
1177
1178 // These functions are called with MenuListPart or MenulistButtonPart appearance by RenderMenuList, or with TextFieldPart appearance by AutofillPopupMenuClient.
1179 // We assume only AutofillPopupMenuClient gives TexfieldPart appearance here.
1180 // We want to change only Autofill padding.
1181 // In the future, we have to separate Autofill popup window logic from WebKit to Chromium.
1182 int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const
1183 {
1184     if (style->appearance() == TextFieldPart)
1185         return autofillPopupHorizontalPadding;
1186
1187     if (style->appearance() == MenulistPart)
1188         return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
1189     if (style->appearance() == MenulistButtonPart)
1190         return styledPopupPaddingLeft * style->effectiveZoom();
1191     return 0;
1192 }
1193
1194 int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
1195 {
1196     if (style->appearance() == TextFieldPart)
1197         return autofillPopupHorizontalPadding;
1198
1199     if (style->appearance() == MenulistPart)
1200         return popupButtonPadding(controlSizeForFont(style))[rightPadding] * style->effectiveZoom();
1201     if (style->appearance() == MenulistButtonPart) {
1202         float fontScale = style->fontSize() / baseFontSize;
1203         float arrowWidth = baseArrowWidth * fontScale;
1204         return static_cast<int>(ceilf(arrowWidth + (arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator) * style->effectiveZoom()));
1205     }
1206     return 0;
1207 }
1208
1209 int RenderThemeChromiumMac::popupInternalPaddingTop(RenderStyle* style) const
1210 {
1211     if (style->appearance() == MenulistPart)
1212         return popupButtonPadding(controlSizeForFont(style))[topPadding] * style->effectiveZoom();
1213     if (style->appearance() == MenulistButtonPart)
1214         return styledPopupPaddingTop * style->effectiveZoom();
1215     return 0;
1216 }
1217
1218 int RenderThemeChromiumMac::popupInternalPaddingBottom(RenderStyle* style) const
1219 {
1220     if (style->appearance() == MenulistPart)
1221         return popupButtonPadding(controlSizeForFont(style))[bottomPadding] * style->effectiveZoom();
1222     if (style->appearance() == MenulistButtonPart)
1223         return styledPopupPaddingBottom * style->effectiveZoom();
1224     return 0;
1225 }
1226
1227 void RenderThemeChromiumMac::adjustMenuListButtonStyle(RenderStyle* style, Element*) const
1228 {
1229     float fontScale = style->fontSize() / baseFontSize;
1230
1231     style->resetPadding();
1232     style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up?
1233
1234     const int minHeight = 15;
1235     style->setMinHeight(Length(minHeight, Fixed));
1236
1237     style->setLineHeight(RenderStyle::initialLineHeight());
1238 }
1239
1240 void RenderThemeChromiumMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
1241 {
1242     NSPopUpButtonCell* popupButton = this->popupButton();
1243
1244     // Set the control size based off the rectangle we're painting into.
1245     setControlSize(popupButton, popupButtonSizes(), r.size(), o->style()->effectiveZoom());
1246
1247     // Update the various states we respond to.
1248     updateActiveState(popupButton, o);
1249     updateCheckedState(popupButton, o);
1250     updateEnabledState(popupButton, o);
1251     updatePressedState(popupButton, o);
1252 #if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
1253     updateFocusedState(popupButton, o);
1254 #endif
1255 }
1256
1257 const IntSize* RenderThemeChromiumMac::menuListSizes() const
1258 {
1259     static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
1260     return sizes;
1261 }
1262
1263 int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const
1264 {
1265     return sizeForSystemFont(style, menuListSizes()).width();
1266 }
1267
1268 const int sliderTrackWidth = 5;
1269 const int sliderTrackBorderWidth = 1;
1270
1271 bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1272 {
1273     paintSliderTicks(o, paintInfo, r);
1274
1275     float zoomLevel = o->style()->effectiveZoom();
1276     FloatRect unzoomedRect = r;
1277
1278     if (o->style()->appearance() ==  SliderHorizontalPart || o->style()->appearance() ==  MediaSliderPart) {
1279         unzoomedRect.setY(ceilf(unzoomedRect.y() + unzoomedRect.height() / 2 - zoomLevel * sliderTrackWidth / 2));
1280         unzoomedRect.setHeight(zoomLevel * sliderTrackWidth);
1281     } else if (o->style()->appearance() == SliderVerticalPart) {
1282         unzoomedRect.setX(ceilf(unzoomedRect.x() + unzoomedRect.width() / 2 - zoomLevel * sliderTrackWidth / 2));
1283         unzoomedRect.setWidth(zoomLevel * sliderTrackWidth);
1284     }
1285
1286     if (zoomLevel != 1) {
1287         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1288         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1289     }
1290
1291     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1292     if (zoomLevel != 1) {
1293         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1294         paintInfo.context->scale(zoomLevel, zoomLevel);
1295         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1296     }
1297
1298     Color fillColor(205, 205, 205);
1299     Color borderGradientTopColor(109, 109, 109);
1300     Color borderGradientBottomColor(181, 181, 181);
1301     Color shadowColor(0, 0, 0, 118);
1302
1303     if (!isEnabled(o)) {
1304         Color tintColor(255, 255, 255, 128);
1305         fillColor = fillColor.blend(tintColor);
1306         borderGradientTopColor = borderGradientTopColor.blend(tintColor);
1307         borderGradientBottomColor = borderGradientBottomColor.blend(tintColor);
1308         shadowColor = shadowColor.blend(tintColor);
1309     }
1310
1311     Color tintColor;
1312     if (!isEnabled(o))
1313         tintColor = Color(255, 255, 255, 128);
1314
1315     bool isVerticalSlider = o->style()->appearance() == SliderVerticalPart;
1316
1317     int fillRadiusSize = (sliderTrackWidth - sliderTrackBorderWidth) / 2;
1318     IntSize fillRadius(fillRadiusSize, fillRadiusSize);
1319     IntRect fillBounds = enclosedIntRect(unzoomedRect);
1320     RoundedRect fillRect(fillBounds, fillRadius, fillRadius, fillRadius, fillRadius);
1321     paintInfo.context->fillRoundedRect(fillRect, fillColor);
1322
1323     IntSize shadowOffset(isVerticalSlider ? 1 : 0,
1324                          isVerticalSlider ? 0 : 1);
1325     int shadowBlur = 3;
1326     int shadowSpread = 0;
1327     paintInfo.context->save();
1328     paintInfo.context->drawInnerShadow(fillRect, shadowColor, shadowOffset, shadowBlur, shadowSpread);
1329     paintInfo.context->restore();
1330
1331     RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(),
1332         isVerticalSlider ? fillBounds.maxXMinYCorner() : fillBounds.minXMaxYCorner());
1333     borderGradient->addColorStop(0.0, borderGradientTopColor);
1334     borderGradient->addColorStop(1.0, borderGradientBottomColor);
1335     Path borderPath;
1336     FloatRect borderRect(unzoomedRect);
1337     borderRect.inflate(-sliderTrackBorderWidth / 2.0);
1338     float borderRadiusSize = (isVerticalSlider ? borderRect.width() : borderRect.height()) / 2;
1339     FloatSize borderRadius(borderRadiusSize, borderRadiusSize);
1340     borderPath.addRoundedRect(borderRect, borderRadius, borderRadius, borderRadius, borderRadius);
1341     paintInfo.context->setStrokeGradient(borderGradient);
1342     paintInfo.context->setStrokeThickness(sliderTrackBorderWidth);
1343     paintInfo.context->strokePath(borderPath);
1344     return false;
1345 }
1346
1347 const int sliderThumbWidth = 15;
1348 const int sliderThumbHeight = 15;
1349 const int sliderThumbBorderWidth = 1;
1350
1351 bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1352 {
1353     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1354     float zoomLevel = o->style()->effectiveZoom();
1355
1356     FloatRect unzoomedRect(r.x(), r.y(), sliderThumbWidth, sliderThumbHeight);
1357     if (zoomLevel != 1.0f) {
1358         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1359         paintInfo.context->scale(zoomLevel, zoomLevel);
1360         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1361     }
1362
1363     Color fillGradientTopColor(250, 250, 250);
1364     Color fillGradientUpperMiddleColor(244, 244, 244);
1365     Color fillGradientLowerMiddleColor(236, 236, 236);
1366     Color fillGradientBottomColor(238, 238, 238);
1367     Color borderGradientTopColor(151, 151, 151);
1368     Color borderGradientBottomColor(128, 128, 128);
1369     Color shadowColor(0, 0, 0, 36);
1370
1371     if (!isEnabled(o)) {
1372         Color tintColor(255, 255, 255, 128);
1373         fillGradientTopColor = fillGradientTopColor.blend(tintColor);
1374         fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor);
1375         fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor);
1376         fillGradientBottomColor = fillGradientBottomColor.blend(tintColor);
1377         borderGradientTopColor = borderGradientTopColor.blend(tintColor);
1378         borderGradientBottomColor = borderGradientBottomColor.blend(tintColor);
1379         shadowColor = shadowColor.blend(tintColor);
1380     } else if (isPressed(o)) {
1381         Color tintColor(0, 0, 0, 32);
1382         fillGradientTopColor = fillGradientTopColor.blend(tintColor);
1383         fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor);
1384         fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor);
1385         fillGradientBottomColor = fillGradientBottomColor.blend(tintColor);
1386         borderGradientTopColor = borderGradientTopColor.blend(tintColor);
1387         borderGradientBottomColor = borderGradientBottomColor.blend(tintColor);
1388         shadowColor = shadowColor.blend(tintColor);
1389     }
1390
1391     FloatRect borderBounds = unzoomedRect;
1392     borderBounds.inflate(sliderThumbBorderWidth / 2.0);
1393
1394     borderBounds.inflate(-sliderThumbBorderWidth);
1395     FloatSize shadowOffset(0, 1);
1396     paintInfo.context->setShadow(shadowOffset, sliderThumbShadowBlur, shadowColor);
1397     paintInfo.context->setFillColor(Color::black);
1398     paintInfo.context->fillEllipse(borderBounds);
1399     paintInfo.context->clearShadow();
1400
1401     IntRect fillBounds = enclosedIntRect(unzoomedRect);
1402     RefPtr<Gradient> fillGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner());
1403     fillGradient->addColorStop(0.0, fillGradientTopColor);
1404     fillGradient->addColorStop(0.52, fillGradientUpperMiddleColor);
1405     fillGradient->addColorStop(0.52, fillGradientLowerMiddleColor);
1406     fillGradient->addColorStop(1.0, fillGradientBottomColor);
1407     paintInfo.context->setFillGradient(fillGradient);
1408     paintInfo.context->fillEllipse(borderBounds);
1409
1410     RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner());
1411     borderGradient->addColorStop(0.0, borderGradientTopColor);
1412     borderGradient->addColorStop(1.0, borderGradientBottomColor);
1413     paintInfo.context->setStrokeGradient(borderGradient);
1414     paintInfo.context->setStrokeThickness(sliderThumbBorderWidth);
1415     paintInfo.context->strokeEllipse(borderBounds);
1416
1417     if (isFocused(o)) {
1418         Path borderPath;
1419         borderPath.addEllipse(borderBounds);
1420         paintInfo.context->drawFocusRing(borderPath, 5, -2, focusRingColor());
1421     }
1422
1423     return false;
1424 }
1425
1426 bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1427 {
1428     LocalCurrentGraphicsContext localContext(paintInfo.context);
1429
1430     NSSearchFieldCell* search = this->search();
1431     setSearchCellState(o, r);
1432     [search setControlSize:searchFieldControlSizeForFont(o->style())];
1433
1434     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1435
1436     float zoomLevel = o->style()->effectiveZoom();
1437
1438     IntRect unzoomedRect = r;
1439
1440     if (zoomLevel != 1.0f) {
1441         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1442         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1443         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1444         paintInfo.context->scale(zoomLevel, zoomLevel);
1445         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1446     }
1447
1448     // Set the search button to nil before drawing.  Then reset it so we can draw it later.
1449     [search setSearchButtonCell:nil];
1450
1451     [search drawWithFrame:NSRect(unzoomedRect) inView:documentViewFor(o)];
1452
1453     [search setControlView:nil];
1454     [search resetSearchButtonCell];
1455
1456     return false;
1457 }
1458
1459 void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect&)
1460 {
1461     NSSearchFieldCell* search = this->search();
1462
1463     // Update the various states we respond to.
1464     updateActiveState(search, o);
1465     updateEnabledState(search, o);
1466     updateFocusedState(search, o);
1467 }
1468
1469 const IntSize* RenderThemeChromiumMac::searchFieldSizes() const
1470 {
1471     static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) };
1472     return sizes;
1473 }
1474
1475 static const int* searchFieldHorizontalPaddings()
1476 {
1477     static const int sizes[3] = { 3, 2, 1 };
1478     return sizes;
1479 }
1480
1481 void RenderThemeChromiumMac::setSearchFieldSize(RenderStyle* style) const
1482 {
1483     // If the width and height are both specified, then we have nothing to do.
1484     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1485         return;
1486
1487     // Use the font size to determine the intrinsic width of the control.
1488     setSizeFromFont(style, searchFieldSizes());
1489 }
1490
1491 const int searchFieldBorderWidth = 2;
1492 void RenderThemeChromiumMac::adjustSearchFieldStyle(RenderStyle* style, Element*) const
1493 {
1494     // Override border.
1495     style->resetBorder();
1496     const short borderWidth = searchFieldBorderWidth * style->effectiveZoom();
1497     style->setBorderLeftWidth(borderWidth);
1498     style->setBorderLeftStyle(INSET);
1499     style->setBorderRightWidth(borderWidth);
1500     style->setBorderRightStyle(INSET);
1501     style->setBorderBottomWidth(borderWidth);
1502     style->setBorderBottomStyle(INSET);
1503     style->setBorderTopWidth(borderWidth);
1504     style->setBorderTopStyle(INSET);
1505
1506     // Override height.
1507     style->setHeight(Length(Auto));
1508     setSearchFieldSize(style);
1509
1510     NSControlSize controlSize = controlSizeForFont(style);
1511
1512     // Override padding size to match AppKit text positioning.
1513     const int verticalPadding = 1 * style->effectiveZoom();
1514     const int horizontalPadding = searchFieldHorizontalPaddings()[controlSize] * style->effectiveZoom();
1515     style->setPaddingLeft(Length(horizontalPadding, Fixed));
1516     style->setPaddingRight(Length(horizontalPadding, Fixed));
1517     style->setPaddingTop(Length(verticalPadding, Fixed));
1518     style->setPaddingBottom(Length(verticalPadding, Fixed));
1519
1520     setFontFromControlSize(style, controlSize);
1521
1522     style->setBoxShadow(nullptr);
1523 }
1524
1525 bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1526 {
1527     if (!o->node())
1528         return false;
1529     Element* input = o->node()->shadowHost();
1530     if (!input)
1531         input = toElement(o->node());
1532
1533     if (!input->renderer()->isBox())
1534         return false;
1535
1536     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1537
1538     float zoomLevel = o->style()->effectiveZoom();
1539     FloatRect unzoomedRect(r);
1540     if (zoomLevel != 1.0f) {
1541         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1542         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1543         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1544         paintInfo.context->scale(zoomLevel, zoomLevel);
1545         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1546     }
1547
1548     Color fillColor(200, 200, 200);
1549
1550     if (isPressed(o)) {
1551         Color tintColor(0, 0, 0, 32);
1552         fillColor = fillColor.blend(tintColor);
1553     }
1554
1555     float centerX = unzoomedRect.x() + unzoomedRect.width() / 2;
1556     float centerY = unzoomedRect.y() + unzoomedRect.height() / 2;
1557     // The line width is 3px on a regular sized, high DPI NSCancelButtonCell
1558     // (which is 28px wide).
1559     float lineWidth = unzoomedRect.width() * 3 / 28;
1560     // The line length is 16px on a regular sized, high DPI NSCancelButtonCell.
1561     float lineLength = unzoomedRect.width() * 16 / 28;
1562
1563     Path xPath;
1564     FloatSize lineRectRadius(lineWidth / 2, lineWidth / 2);
1565     xPath.addRoundedRect(FloatRect(-lineLength / 2, -lineWidth / 2, lineLength, lineWidth),
1566         lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius);
1567     xPath.addRoundedRect(FloatRect(-lineWidth / 2, -lineLength / 2, lineWidth, lineLength),
1568         lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius);
1569
1570     paintInfo.context->translate(centerX, centerY);
1571     paintInfo.context->rotate(deg2rad(45.0));
1572     paintInfo.context->clipOut(xPath);
1573     paintInfo.context->rotate(deg2rad(-45.0));
1574     paintInfo.context->translate(-centerX, -centerY);
1575
1576     paintInfo.context->setFillColor(fillColor);
1577     paintInfo.context->fillEllipse(unzoomedRect);
1578
1579     return false;
1580 }
1581
1582 const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const
1583 {
1584     static const IntSize sizes[3] = { IntSize(14, 14), IntSize(11, 11), IntSize(9, 9) };
1585     return sizes;
1586 }
1587
1588 void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(RenderStyle* style, Element*) const
1589 {
1590     IntSize size = sizeForSystemFont(style, cancelButtonSizes());
1591     style->setWidth(Length(size.width(), Fixed));
1592     style->setHeight(Length(size.height(), Fixed));
1593     style->setBoxShadow(nullptr);
1594 }
1595
1596 const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const
1597 {
1598     static const IntSize sizes[3] = { IntSize(15, 14), IntSize(16, 13), IntSize(14, 11) };
1599     return sizes;
1600 }
1601
1602 void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(RenderStyle* style, Element*) const
1603 {
1604     NSControlSize controlSize = controlSizeForSystemFont(style);
1605     IntSize searchFieldSize = searchFieldSizes()[controlSize];
1606     int width = searchFieldSize.height() / 2 - searchFieldBorderWidth - searchFieldHorizontalPaddings()[controlSize];
1607     style->setWidth(Length(width, Fixed));
1608     style->setHeight(Length(0, Fixed));
1609     style->setBoxShadow(nullptr);
1610 }
1611
1612 bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
1613 {
1614     return false;
1615 }
1616
1617 void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(RenderStyle* style, Element*) const
1618 {
1619     IntSize size = sizeForSystemFont(style, resultsButtonSizes());
1620     style->setWidth(Length(size.width(), Fixed));
1621     style->setHeight(Length(size.height(), Fixed));
1622     style->setBoxShadow(nullptr);
1623 }
1624
1625 bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
1626 {
1627     if (!o->node())
1628         return false;
1629     Node* input = o->node()->shadowHost();
1630     if (!input)
1631         input = o->node();
1632     if (!input->renderer()->isBox())
1633         return false;
1634
1635     GraphicsContextStateSaver stateSaver(*paintInfo.context);
1636
1637     float zoomLevel = o->style()->effectiveZoom();
1638     FloatRect unzoomedRect(r);
1639     if (zoomLevel != 1) {
1640         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1641         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1642         paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
1643         paintInfo.context->scale(zoomLevel, zoomLevel);
1644         paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1645     }
1646
1647     LocalCurrentGraphicsContext localContext(paintInfo.context);
1648
1649     NSSearchFieldCell* search = this->search();
1650     setSearchCellState(input->renderer(), r);
1651     [search setControlSize:searchFieldControlSizeForFont(o->style())];
1652     if ([search searchMenuTemplate] != nil)
1653         [search setSearchMenuTemplate:nil];
1654
1655     updateActiveState([search searchButtonCell], o);
1656
1657     [[search searchButtonCell] drawWithFrame:unzoomedRect inView:documentViewFor(o)];
1658     [[search searchButtonCell] setControlView:nil];
1659     return false;
1660 }
1661
1662 IntSize RenderThemeChromiumMac::sliderTickSize() const
1663 {
1664     return IntSize(1, 3);
1665 }
1666
1667 int RenderThemeChromiumMac::sliderTickOffsetFromTrackCenter() const
1668 {
1669     return -9;
1670 }
1671
1672 void RenderThemeChromiumMac::adjustSliderThumbSize(RenderStyle* style, Element*) const
1673 {
1674     float zoomLevel = style->effectiveZoom();
1675     if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) {
1676         style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
1677         style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
1678     }
1679
1680     adjustMediaSliderThumbSize(style);
1681 }
1682
1683 NSPopUpButtonCell* RenderThemeChromiumMac::popupButton() const
1684 {
1685     if (!m_popupButton) {
1686         m_popupButton.adoptNS([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
1687         [m_popupButton.get() setUsesItemFromMenu:NO];
1688         [m_popupButton.get() setFocusRingType:NSFocusRingTypeExterior];
1689     }
1690
1691     return m_popupButton.get();
1692 }
1693
1694 NSSearchFieldCell* RenderThemeChromiumMac::search() const
1695 {
1696     if (!m_search) {
1697         m_search.adoptNS([[NSSearchFieldCell alloc] initTextCell:@""]);
1698         [m_search.get() setBezelStyle:NSTextFieldRoundedBezel];
1699         [m_search.get() setBezeled:YES];
1700         [m_search.get() setEditable:YES];
1701         [m_search.get() setFocusRingType:NSFocusRingTypeExterior];
1702     }
1703
1704     return m_search.get();
1705 }
1706
1707 NSMenu* RenderThemeChromiumMac::searchMenuTemplate() const
1708 {
1709     if (!m_searchMenuTemplate)
1710         m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
1711
1712     return m_searchMenuTemplate.get();
1713 }
1714
1715 NSTextFieldCell* RenderThemeChromiumMac::textField() const
1716 {
1717     if (!m_textField) {
1718         m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]);
1719         [m_textField.get() setBezeled:YES];
1720         [m_textField.get() setEditable:YES];
1721         [m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
1722 #if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
1723         [m_textField.get() setDrawsBackground:YES];
1724         [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
1725 #else
1726         // Post-Lion, WebCore can be in charge of paintinng the background thanks to
1727         // the workaround in place for <rdar://problem/11385461>, which is implemented
1728         // above as _coreUIDrawOptionsWithFrame.
1729         [m_textField.get() setDrawsBackground:NO];
1730 #endif
1731     }
1732
1733     return m_textField.get();
1734 }
1735
1736 String RenderThemeChromiumMac::fileListNameForWidth(Locale& locale, const FileList* fileList, const Font& font, int width) const
1737 {
1738     if (width <= 0)
1739         return String();
1740
1741     String strToTruncate;
1742     if (fileList->isEmpty()) {
1743         strToTruncate = locale.queryString(WebLocalizedString::FileButtonNoFileSelectedLabel);
1744     } else if (fileList->length() == 1) {
1745         File* file = fileList->item(0);
1746         if (file->userVisibility() == File::IsUserVisible)
1747             strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())];
1748         else
1749             strToTruncate = file->name();
1750     } else {
1751         // FIXME: Localization of fileList->length().
1752         return StringTruncator::rightTruncate(locale.queryString(WebLocalizedString::MultipleFileUploadText, String::number(fileList->length())), width, font);
1753     }
1754
1755     return StringTruncator::centerTruncate(strToTruncate, width, font);
1756 }
1757
1758 NSView* FlippedView()
1759 {
1760     static NSView* view = [[RTCMFlippedView alloc] init];
1761     return view;
1762 }
1763
1764 RenderTheme& RenderTheme::theme()
1765 {
1766     DEFINE_STATIC_REF(RenderTheme, renderTheme, (RenderThemeChromiumMac::create()));
1767     return *renderTheme;
1768 }
1769
1770 PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
1771 {
1772     return adoptRef(new RenderThemeChromiumMac);
1773 }
1774
1775 bool RenderThemeChromiumMac::usesTestModeFocusRingColor() const
1776 {
1777     return LayoutTestSupport::isRunningLayoutTest();
1778 }
1779
1780 NSView* RenderThemeChromiumMac::documentViewFor(RenderObject*) const
1781 {
1782     return FlippedView();
1783 }
1784
1785 // Updates the control tint (a.k.a. active state) of |cell| (from |o|).
1786 // In the Chromium port, the renderer runs as a background process and controls'
1787 // NSCell(s) lack a parent NSView. Therefore controls don't have their tint
1788 // color updated correctly when the application is activated/deactivated.
1789 // FocusController's setActive() is called when the application is
1790 // activated/deactivated, which causes a repaint at which time this code is
1791 // called.
1792 // This function should be called before drawing any NSCell-derived controls,
1793 // unless you're sure it isn't needed.
1794 void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* o)
1795 {
1796     NSControlTint oldTint = [cell controlTint];
1797     NSControlTint tint = isActive(o) ? [NSColor currentControlTint] :
1798                                        static_cast<NSControlTint>(NSClearControlTint);
1799
1800     if (tint != oldTint)
1801         [cell setControlTint:tint];
1802 }
1803
1804 bool RenderThemeChromiumMac::shouldShowPlaceholderWhenFocused() const
1805 {
1806     return true;
1807 }
1808
1809 void RenderThemeChromiumMac::adjustMediaSliderThumbSize(RenderStyle* style) const
1810 {
1811     RenderMediaControls::adjustMediaSliderThumbSize(style);
1812 }
1813
1814 bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1815 {
1816     return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
1817 }
1818
1819 bool RenderThemeChromiumMac::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1820 {
1821     return RenderMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect);
1822 }
1823
1824 bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1825 {
1826     return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
1827 }
1828
1829 bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1830 {
1831     return RenderMediaControls::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
1832 }
1833
1834 String RenderThemeChromiumMac::extraFullScreenStyleSheet()
1835 {
1836     // FIXME: Chromium may wish to style its default media controls differently in fullscreen.
1837     return String();
1838 }
1839
1840 String RenderThemeChromiumMac::extraDefaultStyleSheet()
1841 {
1842     return RenderTheme::extraDefaultStyleSheet() +
1843         String(themeChromiumCss, sizeof(themeChromiumCss)) +
1844         String(themeInputMultipleFieldsCss, sizeof(themeInputMultipleFieldsCss)) +
1845         String(themeMacCss, sizeof(themeMacCss));
1846 }
1847
1848 bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1849 {
1850     return true;
1851 }
1852
1853 bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1854 {
1855     return RenderMediaControls::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
1856 }
1857
1858 bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1859 {
1860     return RenderMediaControls::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
1861 }
1862
1863 bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1864 {
1865     return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
1866 }
1867
1868 String RenderThemeChromiumMac::formatMediaControlsTime(float time) const
1869 {
1870     return RenderMediaControls::formatMediaControlsTime(time);
1871 }
1872
1873 String RenderThemeChromiumMac::formatMediaControlsCurrentTime(float currentTime, float duration) const
1874 {
1875     return RenderMediaControls::formatMediaControlsCurrentTime(currentTime, duration);
1876 }
1877
1878 bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1879 {
1880     return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
1881 }
1882
1883 bool RenderThemeChromiumMac::paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
1884 {
1885     return RenderMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsButton, object, paintInfo, rect);
1886 }
1887
1888 bool RenderThemeChromiumMac::shouldUseFallbackTheme(RenderStyle* style) const
1889 {
1890     ControlPart part = style->appearance();
1891     if (part == CheckboxPart || part == RadioPart)
1892         return style->effectiveZoom() != 1;
1893     return false;
1894 }
1895
1896 } // namespace blink