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