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