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