1 /**
2 * This file is part of the theme implementation for form controls in WebCore.
3 *
4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #include "core/rendering/RenderTheme.h"
24
25 #include "core/CSSValueKeywords.h"
26 #include "core/HTMLNames.h"
27 #include "core/InputTypeNames.h"
28 #include "core/dom/Document.h"
29 #include "core/dom/shadow/ElementShadow.h"
30 #include "core/editing/FrameSelection.h"
31 #include "core/fileapi/FileList.h"
32 #include "core/frame/LocalFrame.h"
33 #include "core/html/HTMLCollection.h"
34 #include "core/html/HTMLDataListElement.h"
35 #include "core/html/HTMLDataListOptionsCollection.h"
36 #include "core/html/HTMLFormControlElement.h"
37 #include "core/html/HTMLInputElement.h"
38 #include "core/html/HTMLMeterElement.h"
39 #include "core/html/HTMLOptionElement.h"
40 #include "core/html/parser/HTMLParserIdioms.h"
41 #include "core/html/shadow/MediaControlElements.h"
42 #include "core/html/shadow/ShadowElementNames.h"
43 #include "core/html/shadow/SpinButtonElement.h"
44 #include "core/html/shadow/TextControlInnerElements.h"
45 #include "core/page/FocusController.h"
46 #include "core/page/Page.h"
47 #include "core/frame/Settings.h"
48 #include "core/rendering/PaintInfo.h"
49 #include "core/rendering/RenderMeter.h"
50 #include "core/rendering/RenderView.h"
51 #include "core/rendering/style/RenderStyle.h"
52 #include "platform/FileMetadata.h"
53 #include "platform/FloatConversion.h"
54 #include "platform/RuntimeEnabledFeatures.h"
55 #include "platform/fonts/FontSelector.h"
56 #include "platform/graphics/GraphicsContextStateSaver.h"
57 #include "platform/text/PlatformLocale.h"
58 #include "platform/text/StringTruncator.h"
59 #include "public/platform/Platform.h"
60 #include "public/platform/WebFallbackThemeEngine.h"
61 #include "public/platform/WebRect.h"
62 #include "wtf/text/StringBuilder.h"
63
64 // The methods in this file are shared by all themes on every platform.
65
66 namespace blink {
67
68 using namespace HTMLNames;
69
getWebFallbackThemeState(const RenderTheme * theme,const RenderObject * o)70 static WebFallbackThemeEngine::State getWebFallbackThemeState(const RenderTheme* theme, const RenderObject* o)
71 {
72 if (!theme->isEnabled(o))
73 return WebFallbackThemeEngine::StateDisabled;
74 if (theme->isPressed(o))
75 return WebFallbackThemeEngine::StatePressed;
76 if (theme->isHovered(o))
77 return WebFallbackThemeEngine::StateHover;
78
79 return WebFallbackThemeEngine::StateNormal;
80 }
81
RenderTheme()82 RenderTheme::RenderTheme()
83 : m_hasCustomFocusRingColor(false)
84 #if USE(NEW_THEME)
85 , m_platformTheme(platformTheme())
86 #endif
87 {
88 }
89
adjustStyle(RenderStyle * style,Element * e,const CachedUAStyle * uaStyle)90 void RenderTheme::adjustStyle(RenderStyle* style, Element* e, const CachedUAStyle* uaStyle)
91 {
92 // Force inline and table display styles to be inline-block (except for table- which is block)
93 ControlPart part = style->appearance();
94 if (style->display() == INLINE || style->display() == INLINE_TABLE || style->display() == TABLE_ROW_GROUP
95 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_FOOTER_GROUP
96 || style->display() == TABLE_ROW || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_COLUMN
97 || style->display() == TABLE_CELL || style->display() == TABLE_CAPTION)
98 style->setDisplay(INLINE_BLOCK);
99 else if (style->display() == LIST_ITEM || style->display() == TABLE)
100 style->setDisplay(BLOCK);
101
102 if (uaStyle && uaStyle->hasAppearance && isControlStyled(style, uaStyle)) {
103 if (part == MenulistPart) {
104 style->setAppearance(MenulistButtonPart);
105 part = MenulistButtonPart;
106 } else
107 style->setAppearance(NoControlPart);
108 }
109
110 if (!style->hasAppearance())
111 return;
112
113 if (shouldUseFallbackTheme(style)) {
114 adjustStyleUsingFallbackTheme(style, e);
115 return;
116 }
117
118 #if USE(NEW_THEME)
119 switch (part) {
120 case CheckboxPart:
121 case InnerSpinButtonPart:
122 case RadioPart:
123 case PushButtonPart:
124 case SquareButtonPart:
125 case ButtonPart: {
126 // Border
127 LengthBox borderBox(style->borderTopWidth(), style->borderRightWidth(), style->borderBottomWidth(), style->borderLeftWidth());
128 borderBox = m_platformTheme->controlBorder(part, style->font().fontDescription(), borderBox, style->effectiveZoom());
129 if (borderBox.top().value() != static_cast<int>(style->borderTopWidth())) {
130 if (borderBox.top().value())
131 style->setBorderTopWidth(borderBox.top().value());
132 else
133 style->resetBorderTop();
134 }
135 if (borderBox.right().value() != static_cast<int>(style->borderRightWidth())) {
136 if (borderBox.right().value())
137 style->setBorderRightWidth(borderBox.right().value());
138 else
139 style->resetBorderRight();
140 }
141 if (borderBox.bottom().value() != static_cast<int>(style->borderBottomWidth())) {
142 style->setBorderBottomWidth(borderBox.bottom().value());
143 if (borderBox.bottom().value())
144 style->setBorderBottomWidth(borderBox.bottom().value());
145 else
146 style->resetBorderBottom();
147 }
148 if (borderBox.left().value() != static_cast<int>(style->borderLeftWidth())) {
149 style->setBorderLeftWidth(borderBox.left().value());
150 if (borderBox.left().value())
151 style->setBorderLeftWidth(borderBox.left().value());
152 else
153 style->resetBorderLeft();
154 }
155
156 // Padding
157 LengthBox paddingBox = m_platformTheme->controlPadding(part, style->font().fontDescription(), style->paddingBox(), style->effectiveZoom());
158 if (paddingBox != style->paddingBox())
159 style->setPaddingBox(paddingBox);
160
161 // Whitespace
162 if (m_platformTheme->controlRequiresPreWhiteSpace(part))
163 style->setWhiteSpace(PRE);
164
165 // Width / Height
166 // The width and height here are affected by the zoom.
167 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account.
168 LengthSize controlSize = m_platformTheme->controlSize(part, style->font().fontDescription(), LengthSize(style->width(), style->height()), style->effectiveZoom());
169 if (controlSize.width() != style->width())
170 style->setWidth(controlSize.width());
171 if (controlSize.height() != style->height())
172 style->setHeight(controlSize.height());
173
174 // Min-Width / Min-Height
175 LengthSize minControlSize = m_platformTheme->minimumControlSize(part, style->font().fontDescription(), style->effectiveZoom());
176 if (minControlSize.width() != style->minWidth())
177 style->setMinWidth(minControlSize.width());
178 if (minControlSize.height() != style->minHeight())
179 style->setMinHeight(minControlSize.height());
180
181 // Font
182 FontDescription controlFont = m_platformTheme->controlFont(part, style->font().fontDescription(), style->effectiveZoom());
183 if (controlFont != style->font().fontDescription()) {
184 // Reset our line-height
185 style->setLineHeight(RenderStyle::initialLineHeight());
186
187 // Now update our font.
188 if (style->setFontDescription(controlFont))
189 style->font().update(nullptr);
190 }
191 }
192 default:
193 break;
194 }
195 #endif
196
197 // Call the appropriate style adjustment method based off the appearance value.
198 switch (style->appearance()) {
199 #if !USE(NEW_THEME)
200 case CheckboxPart:
201 return adjustCheckboxStyle(style, e);
202 case RadioPart:
203 return adjustRadioStyle(style, e);
204 case PushButtonPart:
205 case SquareButtonPart:
206 case ButtonPart:
207 return adjustButtonStyle(style, e);
208 case InnerSpinButtonPart:
209 return adjustInnerSpinButtonStyle(style, e);
210 #endif
211 case MenulistPart:
212 return adjustMenuListStyle(style, e);
213 case MenulistButtonPart:
214 return adjustMenuListButtonStyle(style, e);
215 case SliderThumbHorizontalPart:
216 case SliderThumbVerticalPart:
217 return adjustSliderThumbStyle(style, e);
218 case SearchFieldPart:
219 return adjustSearchFieldStyle(style, e);
220 case SearchFieldCancelButtonPart:
221 return adjustSearchFieldCancelButtonStyle(style, e);
222 case SearchFieldDecorationPart:
223 return adjustSearchFieldDecorationStyle(style, e);
224 case SearchFieldResultsDecorationPart:
225 return adjustSearchFieldResultsDecorationStyle(style, e);
226 default:
227 break;
228 }
229 }
230
paint(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)231 bool RenderTheme::paint(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
232 {
233 ControlPart part = o->style()->appearance();
234
235 if (shouldUseFallbackTheme(o->style()))
236 return paintUsingFallbackTheme(o, paintInfo, r);
237
238 #if USE(NEW_THEME)
239 switch (part) {
240 case CheckboxPart:
241 case RadioPart:
242 case PushButtonPart:
243 case SquareButtonPart:
244 case ButtonPart:
245 case InnerSpinButtonPart:
246 m_platformTheme->paint(part, controlStatesForRenderer(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->style()->effectiveZoom(), o->view()->frameView());
247 return false;
248 default:
249 break;
250 }
251 #endif
252
253 // Call the appropriate paint method based off the appearance value.
254 switch (part) {
255 #if !USE(NEW_THEME)
256 case CheckboxPart:
257 return paintCheckbox(o, paintInfo, r);
258 case RadioPart:
259 return paintRadio(o, paintInfo, r);
260 case PushButtonPart:
261 case SquareButtonPart:
262 case ButtonPart:
263 return paintButton(o, paintInfo, r);
264 case InnerSpinButtonPart:
265 return paintInnerSpinButton(o, paintInfo, r);
266 #endif
267 case MenulistPart:
268 return paintMenuList(o, paintInfo, r);
269 case MeterPart:
270 case RelevancyLevelIndicatorPart:
271 case ContinuousCapacityLevelIndicatorPart:
272 case DiscreteCapacityLevelIndicatorPart:
273 case RatingLevelIndicatorPart:
274 return paintMeter(o, paintInfo, r);
275 case ProgressBarPart:
276 return paintProgressBar(o, paintInfo, r);
277 case SliderHorizontalPart:
278 case SliderVerticalPart:
279 return paintSliderTrack(o, paintInfo, r);
280 case SliderThumbHorizontalPart:
281 case SliderThumbVerticalPart:
282 return paintSliderThumb(o, paintInfo, r);
283 case MediaEnterFullscreenButtonPart:
284 case MediaExitFullscreenButtonPart:
285 return paintMediaFullscreenButton(o, paintInfo, r);
286 case MediaPlayButtonPart:
287 return paintMediaPlayButton(o, paintInfo, r);
288 case MediaOverlayPlayButtonPart:
289 return paintMediaOverlayPlayButton(o, paintInfo, r);
290 case MediaMuteButtonPart:
291 return paintMediaMuteButton(o, paintInfo, r);
292 case MediaToggleClosedCaptionsButtonPart:
293 return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
294 case MediaSliderPart:
295 return paintMediaSliderTrack(o, paintInfo, r);
296 case MediaSliderThumbPart:
297 return paintMediaSliderThumb(o, paintInfo, r);
298 case MediaVolumeSliderContainerPart:
299 return paintMediaVolumeSliderContainer(o, paintInfo, r);
300 case MediaVolumeSliderPart:
301 return paintMediaVolumeSliderTrack(o, paintInfo, r);
302 case MediaVolumeSliderThumbPart:
303 return paintMediaVolumeSliderThumb(o, paintInfo, r);
304 case MediaFullScreenVolumeSliderPart:
305 return paintMediaFullScreenVolumeSliderTrack(o, paintInfo, r);
306 case MediaFullScreenVolumeSliderThumbPart:
307 return paintMediaFullScreenVolumeSliderThumb(o, paintInfo, r);
308 case MediaTimeRemainingPart:
309 return paintMediaTimeRemaining(o, paintInfo, r);
310 case MediaCurrentTimePart:
311 return paintMediaCurrentTime(o, paintInfo, r);
312 case MediaControlsBackgroundPart:
313 return paintMediaControlsBackground(o, paintInfo, r);
314 case MediaCastOffButtonPart:
315 return paintMediaCastButton(o, paintInfo, r);
316 case MediaOverlayCastOffButtonPart:
317 return paintMediaCastButton(o, paintInfo, r);
318 case MenulistButtonPart:
319 case TextFieldPart:
320 case TextAreaPart:
321 return true;
322 case SearchFieldPart:
323 return paintSearchField(o, paintInfo, r);
324 case SearchFieldCancelButtonPart:
325 return paintSearchFieldCancelButton(o, paintInfo, r);
326 case SearchFieldDecorationPart:
327 return paintSearchFieldDecoration(o, paintInfo, r);
328 case SearchFieldResultsDecorationPart:
329 return paintSearchFieldResultsDecoration(o, paintInfo, r);
330 default:
331 break;
332 }
333
334 return true; // We don't support the appearance, so let the normal background/border paint.
335 }
336
paintBorderOnly(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)337 bool RenderTheme::paintBorderOnly(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
338 {
339 // Call the appropriate paint method based off the appearance value.
340 switch (o->style()->appearance()) {
341 case TextFieldPart:
342 return paintTextField(o, paintInfo, r);
343 case TextAreaPart:
344 return paintTextArea(o, paintInfo, r);
345 case MenulistButtonPart:
346 case SearchFieldPart:
347 case ListboxPart:
348 return true;
349 case CheckboxPart:
350 case RadioPart:
351 case PushButtonPart:
352 case SquareButtonPart:
353 case ButtonPart:
354 case MenulistPart:
355 case MeterPart:
356 case RelevancyLevelIndicatorPart:
357 case ContinuousCapacityLevelIndicatorPart:
358 case DiscreteCapacityLevelIndicatorPart:
359 case RatingLevelIndicatorPart:
360 case ProgressBarPart:
361 case SliderHorizontalPart:
362 case SliderVerticalPart:
363 case SliderThumbHorizontalPart:
364 case SliderThumbVerticalPart:
365 case SearchFieldCancelButtonPart:
366 case SearchFieldDecorationPart:
367 case SearchFieldResultsDecorationPart:
368 default:
369 break;
370 }
371
372 return false;
373 }
374
paintDecorations(RenderObject * o,const PaintInfo & paintInfo,const IntRect & r)375 bool RenderTheme::paintDecorations(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
376 {
377 // Call the appropriate paint method based off the appearance value.
378 switch (o->style()->appearance()) {
379 case MenulistButtonPart:
380 return paintMenuListButton(o, paintInfo, r);
381 case TextFieldPart:
382 case TextAreaPart:
383 case CheckboxPart:
384 case RadioPart:
385 case PushButtonPart:
386 case SquareButtonPart:
387 case ButtonPart:
388 case MenulistPart:
389 case MeterPart:
390 case RelevancyLevelIndicatorPart:
391 case ContinuousCapacityLevelIndicatorPart:
392 case DiscreteCapacityLevelIndicatorPart:
393 case RatingLevelIndicatorPart:
394 case ProgressBarPart:
395 case SliderHorizontalPart:
396 case SliderVerticalPart:
397 case SliderThumbHorizontalPart:
398 case SliderThumbVerticalPart:
399 case SearchFieldPart:
400 case SearchFieldCancelButtonPart:
401 case SearchFieldDecorationPart:
402 case SearchFieldResultsDecorationPart:
403 default:
404 break;
405 }
406
407 return false;
408 }
409
extraDefaultStyleSheet()410 String RenderTheme::extraDefaultStyleSheet()
411 {
412 StringBuilder runtimeCSS;
413 if (RuntimeEnabledFeatures::contextMenuEnabled())
414 runtimeCSS.appendLiteral("menu[type=\"popup\" i] { display: none; }");
415 return runtimeCSS.toString();
416 }
417
formatMediaControlsTime(float time) const418 String RenderTheme::formatMediaControlsTime(float time) const
419 {
420 if (!std::isfinite(time))
421 time = 0;
422 int seconds = (int)fabsf(time);
423 int hours = seconds / (60 * 60);
424 int minutes = (seconds / 60) % 60;
425 seconds %= 60;
426 if (hours) {
427 if (hours > 9)
428 return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
429
430 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
431 }
432
433 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
434 }
435
formatMediaControlsCurrentTime(float currentTime,float) const436 String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
437 {
438 return formatMediaControlsTime(currentTime);
439 }
440
activeSelectionBackgroundColor() const441 Color RenderTheme::activeSelectionBackgroundColor() const
442 {
443 return platformActiveSelectionBackgroundColor().blendWithWhite();
444 }
445
inactiveSelectionBackgroundColor() const446 Color RenderTheme::inactiveSelectionBackgroundColor() const
447 {
448 return platformInactiveSelectionBackgroundColor().blendWithWhite();
449 }
450
activeSelectionForegroundColor() const451 Color RenderTheme::activeSelectionForegroundColor() const
452 {
453 return platformActiveSelectionForegroundColor();
454 }
455
inactiveSelectionForegroundColor() const456 Color RenderTheme::inactiveSelectionForegroundColor() const
457 {
458 return platformInactiveSelectionForegroundColor();
459 }
460
activeListBoxSelectionBackgroundColor() const461 Color RenderTheme::activeListBoxSelectionBackgroundColor() const
462 {
463 return platformActiveListBoxSelectionBackgroundColor();
464 }
465
inactiveListBoxSelectionBackgroundColor() const466 Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
467 {
468 return platformInactiveListBoxSelectionBackgroundColor();
469 }
470
activeListBoxSelectionForegroundColor() const471 Color RenderTheme::activeListBoxSelectionForegroundColor() const
472 {
473 return platformActiveListBoxSelectionForegroundColor();
474 }
475
inactiveListBoxSelectionForegroundColor() const476 Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
477 {
478 return platformInactiveListBoxSelectionForegroundColor();
479 }
480
platformActiveSelectionBackgroundColor() const481 Color RenderTheme::platformActiveSelectionBackgroundColor() const
482 {
483 // Use a blue color by default if the platform theme doesn't define anything.
484 return Color(0, 0, 255);
485 }
486
platformActiveSelectionForegroundColor() const487 Color RenderTheme::platformActiveSelectionForegroundColor() const
488 {
489 // Use a white color by default if the platform theme doesn't define anything.
490 return Color::white;
491 }
492
platformInactiveSelectionBackgroundColor() const493 Color RenderTheme::platformInactiveSelectionBackgroundColor() const
494 {
495 // Use a grey color by default if the platform theme doesn't define anything.
496 // This color matches Firefox's inactive color.
497 return Color(176, 176, 176);
498 }
499
platformInactiveSelectionForegroundColor() const500 Color RenderTheme::platformInactiveSelectionForegroundColor() const
501 {
502 // Use a black color by default.
503 return Color::black;
504 }
505
platformActiveListBoxSelectionBackgroundColor() const506 Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
507 {
508 return platformActiveSelectionBackgroundColor();
509 }
510
platformActiveListBoxSelectionForegroundColor() const511 Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
512 {
513 return platformActiveSelectionForegroundColor();
514 }
515
platformInactiveListBoxSelectionBackgroundColor() const516 Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
517 {
518 return platformInactiveSelectionBackgroundColor();
519 }
520
platformInactiveListBoxSelectionForegroundColor() const521 Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
522 {
523 return platformInactiveSelectionForegroundColor();
524 }
525
baselinePosition(const RenderObject * o) const526 int RenderTheme::baselinePosition(const RenderObject* o) const
527 {
528 if (!o->isBox())
529 return 0;
530
531 const RenderBox* box = toRenderBox(o);
532
533 #if USE(NEW_THEME)
534 return box->height() + box->marginTop() + m_platformTheme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
535 #else
536 return box->height() + box->marginTop();
537 #endif
538 }
539
isControlContainer(ControlPart appearance) const540 bool RenderTheme::isControlContainer(ControlPart appearance) const
541 {
542 // There are more leaves than this, but we'll patch this function as we add support for
543 // more controls.
544 return appearance != CheckboxPart && appearance != RadioPart;
545 }
546
isBackgroundOrBorderStyled(const RenderStyle & style,const CachedUAStyle & uaStyle)547 static bool isBackgroundOrBorderStyled(const RenderStyle& style, const CachedUAStyle& uaStyle)
548 {
549 // Code below excludes the background-repeat from comparison by resetting it
550 FillLayer backgroundCopy = uaStyle.backgroundLayers;
551 FillLayer backgroundLayersCopy = style.backgroundLayers();
552 backgroundCopy.setRepeatX(NoRepeatFill);
553 backgroundCopy.setRepeatY(NoRepeatFill);
554 backgroundLayersCopy.setRepeatX(NoRepeatFill);
555 backgroundLayersCopy.setRepeatY(NoRepeatFill);
556 // Test the style to see if the UA border and background match.
557 return style.border() != uaStyle.border
558 || backgroundLayersCopy != backgroundCopy
559 || style.visitedDependentColor(CSSPropertyBackgroundColor) != uaStyle.backgroundColor;
560 }
561
isControlStyled(const RenderStyle * style,const CachedUAStyle * uaStyle) const562 bool RenderTheme::isControlStyled(const RenderStyle* style, const CachedUAStyle* uaStyle) const
563 {
564 ASSERT(uaStyle);
565
566 switch (style->appearance()) {
567 case PushButtonPart:
568 case SquareButtonPart:
569 case ButtonPart:
570 case ProgressBarPart:
571 case MeterPart:
572 case RelevancyLevelIndicatorPart:
573 case ContinuousCapacityLevelIndicatorPart:
574 case DiscreteCapacityLevelIndicatorPart:
575 case RatingLevelIndicatorPart:
576 return isBackgroundOrBorderStyled(*style, *uaStyle);
577
578 case MenulistPart:
579 case SearchFieldPart:
580 case TextAreaPart:
581 case TextFieldPart:
582 return isBackgroundOrBorderStyled(*style, *uaStyle) || style->boxShadow();
583
584 case SliderHorizontalPart:
585 case SliderVerticalPart:
586 return style->boxShadow();
587
588 default:
589 return false;
590 }
591 }
592
adjustPaintInvalidationRect(const RenderObject * o,IntRect & r)593 void RenderTheme::adjustPaintInvalidationRect(const RenderObject* o, IntRect& r)
594 {
595 #if USE(NEW_THEME)
596 m_platformTheme->inflateControlPaintRect(o->style()->appearance(), controlStatesForRenderer(o), r, o->style()->effectiveZoom());
597 #endif
598 }
599
shouldDrawDefaultFocusRing(RenderObject * renderer) const600 bool RenderTheme::shouldDrawDefaultFocusRing(RenderObject* renderer) const
601 {
602 if (supportsFocusRing(renderer->style()))
603 return false;
604 Node* node = renderer->node();
605 if (!node)
606 return true;
607 if (!renderer->style()->hasAppearance() && !node->isLink())
608 return true;
609 // We can't use RenderTheme::isFocused because outline:auto might be
610 // specified to non-:focus rulesets.
611 if (node->focused() && !node->shouldHaveFocusAppearance())
612 return false;
613 return true;
614 }
615
supportsFocusRing(const RenderStyle * style) const616 bool RenderTheme::supportsFocusRing(const RenderStyle* style) const
617 {
618 return (style->hasAppearance() && style->appearance() != TextFieldPart && style->appearance() != TextAreaPart && style->appearance() != MenulistButtonPart && style->appearance() != ListboxPart);
619 }
620
stateChanged(RenderObject * o,ControlState state) const621 bool RenderTheme::stateChanged(RenderObject* o, ControlState state) const
622 {
623 // Default implementation assumes the controls don't respond to changes in :hover state
624 if (state == HoverControlState && !supportsHover(o->style()))
625 return false;
626
627 // Assume pressed state is only responded to if the control is enabled.
628 if (state == PressedControlState && !isEnabled(o))
629 return false;
630
631 o->setShouldDoFullPaintInvalidation(true);
632 return true;
633 }
634
controlStatesForRenderer(const RenderObject * o) const635 ControlStates RenderTheme::controlStatesForRenderer(const RenderObject* o) const
636 {
637 ControlStates result = 0;
638 if (isHovered(o)) {
639 result |= HoverControlState;
640 if (isSpinUpButtonPartHovered(o))
641 result |= SpinUpControlState;
642 }
643 if (isPressed(o)) {
644 result |= PressedControlState;
645 if (isSpinUpButtonPartPressed(o))
646 result |= SpinUpControlState;
647 }
648 if (isFocused(o) && o->style()->outlineStyleIsAuto())
649 result |= FocusControlState;
650 if (isEnabled(o))
651 result |= EnabledControlState;
652 if (isChecked(o))
653 result |= CheckedControlState;
654 if (isReadOnlyControl(o))
655 result |= ReadOnlyControlState;
656 if (!isActive(o))
657 result |= WindowInactiveControlState;
658 if (isIndeterminate(o))
659 result |= IndeterminateControlState;
660 return result;
661 }
662
isActive(const RenderObject * o) const663 bool RenderTheme::isActive(const RenderObject* o) const
664 {
665 Node* node = o->node();
666 if (!node)
667 return false;
668
669 Page* page = node->document().page();
670 if (!page)
671 return false;
672
673 return page->focusController().isActive();
674 }
675
isChecked(const RenderObject * o) const676 bool RenderTheme::isChecked(const RenderObject* o) const
677 {
678 if (!isHTMLInputElement(o->node()))
679 return false;
680 return toHTMLInputElement(o->node())->shouldAppearChecked();
681 }
682
isIndeterminate(const RenderObject * o) const683 bool RenderTheme::isIndeterminate(const RenderObject* o) const
684 {
685 if (!isHTMLInputElement(o->node()))
686 return false;
687 return toHTMLInputElement(o->node())->shouldAppearIndeterminate();
688 }
689
isEnabled(const RenderObject * o) const690 bool RenderTheme::isEnabled(const RenderObject* o) const
691 {
692 Node* node = o->node();
693 if (!node || !node->isElementNode())
694 return true;
695 return !toElement(node)->isDisabledFormControl();
696 }
697
isFocused(const RenderObject * o) const698 bool RenderTheme::isFocused(const RenderObject* o) const
699 {
700 Node* node = o->node();
701 if (!node)
702 return false;
703
704 node = node->focusDelegate();
705 Document& document = node->document();
706 LocalFrame* frame = document.frame();
707 return node == document.focusedElement() && node->focused() && node->shouldHaveFocusAppearance() && frame && frame->selection().isFocusedAndActive();
708 }
709
isPressed(const RenderObject * o) const710 bool RenderTheme::isPressed(const RenderObject* o) const
711 {
712 if (!o->node())
713 return false;
714 return o->node()->active();
715 }
716
isSpinUpButtonPartPressed(const RenderObject * o) const717 bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
718 {
719 Node* node = o->node();
720 if (!node || !node->active() || !node->isElementNode()
721 || !toElement(node)->isSpinButtonElement())
722 return false;
723 SpinButtonElement* element = toSpinButtonElement(node);
724 return element->upDownState() == SpinButtonElement::Up;
725 }
726
isReadOnlyControl(const RenderObject * o) const727 bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
728 {
729 Node* node = o->node();
730 if (!node || !node->isElementNode() || !toElement(node)->isFormControlElement())
731 return false;
732 HTMLFormControlElement* element = toHTMLFormControlElement(node);
733 return element->isReadOnly();
734 }
735
isHovered(const RenderObject * o) const736 bool RenderTheme::isHovered(const RenderObject* o) const
737 {
738 Node* node = o->node();
739 if (!node)
740 return false;
741 if (!node->isElementNode() || !toElement(node)->isSpinButtonElement())
742 return node->hovered();
743 SpinButtonElement* element = toSpinButtonElement(node);
744 return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
745 }
746
isSpinUpButtonPartHovered(const RenderObject * o) const747 bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
748 {
749 Node* node = o->node();
750 if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement())
751 return false;
752 SpinButtonElement* element = toSpinButtonElement(node);
753 return element->upDownState() == SpinButtonElement::Up;
754 }
755
756 #if !USE(NEW_THEME)
757
adjustCheckboxStyle(RenderStyle * style,Element *) const758 void RenderTheme::adjustCheckboxStyle(RenderStyle* style, Element*) const
759 {
760 // A summary of the rules for checkbox designed to match WinIE:
761 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
762 // font-size - not honored (control has no text), but we use it to decide which control size to use.
763 setCheckboxSize(style);
764
765 // padding - not honored by WinIE, needs to be removed.
766 style->resetPadding();
767
768 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
769 // for now, we will not honor it.
770 style->resetBorder();
771 }
772
adjustRadioStyle(RenderStyle * style,Element *) const773 void RenderTheme::adjustRadioStyle(RenderStyle* style, Element*) const
774 {
775 // A summary of the rules for checkbox designed to match WinIE:
776 // width/height - honored (WinIE actually scales its control for small widths, but lets it overflow for small heights.)
777 // font-size - not honored (control has no text), but we use it to decide which control size to use.
778 setRadioSize(style);
779
780 // padding - not honored by WinIE, needs to be removed.
781 style->resetPadding();
782
783 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
784 // for now, we will not honor it.
785 style->resetBorder();
786 }
787
adjustButtonStyle(RenderStyle * style,Element *) const788 void RenderTheme::adjustButtonStyle(RenderStyle* style, Element*) const
789 {
790 }
791
adjustInnerSpinButtonStyle(RenderStyle *,Element *) const792 void RenderTheme::adjustInnerSpinButtonStyle(RenderStyle*, Element*) const
793 {
794 }
795 #endif
796
adjustMenuListStyle(RenderStyle *,Element *) const797 void RenderTheme::adjustMenuListStyle(RenderStyle*, Element*) const
798 {
799 }
800
meterSizeForBounds(const RenderMeter *,const IntRect & bounds) const801 IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
802 {
803 return bounds.size();
804 }
805
supportsMeter(ControlPart) const806 bool RenderTheme::supportsMeter(ControlPart) const
807 {
808 return false;
809 }
810
paintMeter(RenderObject *,const PaintInfo &,const IntRect &)811 bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
812 {
813 return true;
814 }
815
paintSliderTicks(RenderObject * o,const PaintInfo & paintInfo,const IntRect & rect)816 void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
817 {
818 Node* node = o->node();
819 if (!isHTMLInputElement(node))
820 return;
821
822 HTMLInputElement* input = toHTMLInputElement(node);
823 if (input->type() != InputTypeNames::range)
824 return;
825
826 HTMLDataListElement* dataList = input->dataList();
827 if (!dataList)
828 return;
829
830 double min = input->minimum();
831 double max = input->maximum();
832 ControlPart part = o->style()->appearance();
833 // We don't support ticks on alternate sliders like MediaVolumeSliders.
834 if (part != SliderHorizontalPart && part != SliderVerticalPart)
835 return;
836 bool isHorizontal = part == SliderHorizontalPart;
837
838 IntSize thumbSize;
839 RenderObject* thumbRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderThumb())->renderer();
840 if (thumbRenderer) {
841 RenderStyle* thumbStyle = thumbRenderer->style();
842 int thumbWidth = thumbStyle->width().intValue();
843 int thumbHeight = thumbStyle->height().intValue();
844 thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
845 thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
846 }
847
848 IntSize tickSize = sliderTickSize();
849 float zoomFactor = o->style()->effectiveZoom();
850 FloatRect tickRect;
851 int tickRegionSideMargin = 0;
852 int tickRegionWidth = 0;
853 IntRect trackBounds;
854 RenderObject* trackRenderer = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack())->renderer();
855 // We can ignoring transforms because transform is handled by the graphics context.
856 if (trackRenderer)
857 trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
858 IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms();
859
860 // Make position relative to the transformed ancestor element.
861 trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
862 trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
863
864 if (isHorizontal) {
865 tickRect.setWidth(floor(tickSize.width() * zoomFactor));
866 tickRect.setHeight(floor(tickSize.height() * zoomFactor));
867 tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
868 tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
869 tickRegionWidth = trackBounds.width() - thumbSize.width();
870 } else {
871 tickRect.setWidth(floor(tickSize.height() * zoomFactor));
872 tickRect.setHeight(floor(tickSize.width() * zoomFactor));
873 tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
874 tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
875 tickRegionWidth = trackBounds.height() - thumbSize.width();
876 }
877 RefPtrWillBeRawPtr<HTMLDataListOptionsCollection> options = dataList->options();
878 GraphicsContextStateSaver stateSaver(*paintInfo.context);
879 paintInfo.context->setFillColor(o->resolveColor(CSSPropertyColor));
880 for (unsigned i = 0; HTMLOptionElement* optionElement = options->item(i); i++) {
881 String value = optionElement->value();
882 if (!input->isValidValue(value))
883 continue;
884 double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
885 double tickFraction = (parsedValue - min) / (max - min);
886 double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
887 double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
888 if (isHorizontal)
889 tickRect.setX(tickPosition);
890 else
891 tickRect.setY(tickPosition);
892 paintInfo.context->fillRect(tickRect);
893 }
894 }
895
animationRepeatIntervalForProgressBar(RenderProgress *) const896 double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
897 {
898 return 0;
899 }
900
animationDurationForProgressBar(RenderProgress *) const901 double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
902 {
903 return 0;
904 }
905
shouldHaveSpinButton(HTMLInputElement * inputElement) const906 bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
907 {
908 return inputElement->isSteppable() && inputElement->type() != InputTypeNames::range;
909 }
910
adjustMenuListButtonStyle(RenderStyle *,Element *) const911 void RenderTheme::adjustMenuListButtonStyle(RenderStyle*, Element*) const
912 {
913 }
914
adjustSliderThumbStyle(RenderStyle * style,Element * element) const915 void RenderTheme::adjustSliderThumbStyle(RenderStyle* style, Element* element) const
916 {
917 adjustSliderThumbSize(style, element);
918 }
919
adjustSliderThumbSize(RenderStyle *,Element *) const920 void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const
921 {
922 }
923
adjustSearchFieldStyle(RenderStyle *,Element *) const924 void RenderTheme::adjustSearchFieldStyle(RenderStyle*, Element*) const
925 {
926 }
927
adjustSearchFieldCancelButtonStyle(RenderStyle *,Element *) const928 void RenderTheme::adjustSearchFieldCancelButtonStyle(RenderStyle*, Element*) const
929 {
930 }
931
adjustSearchFieldDecorationStyle(RenderStyle *,Element *) const932 void RenderTheme::adjustSearchFieldDecorationStyle(RenderStyle*, Element*) const
933 {
934 }
935
adjustSearchFieldResultsDecorationStyle(RenderStyle *,Element *) const936 void RenderTheme::adjustSearchFieldResultsDecorationStyle(RenderStyle*, Element*) const
937 {
938 }
939
platformColorsDidChange()940 void RenderTheme::platformColorsDidChange()
941 {
942 Page::scheduleForcedStyleRecalcForAllPages();
943 }
944
systemColor(CSSValueID cssValueId) const945 Color RenderTheme::systemColor(CSSValueID cssValueId) const
946 {
947 switch (cssValueId) {
948 case CSSValueActiveborder:
949 return 0xFFFFFFFF;
950 case CSSValueActivecaption:
951 return 0xFFCCCCCC;
952 case CSSValueAppworkspace:
953 return 0xFFFFFFFF;
954 case CSSValueBackground:
955 return 0xFF6363CE;
956 case CSSValueButtonface:
957 return 0xFFC0C0C0;
958 case CSSValueButtonhighlight:
959 return 0xFFDDDDDD;
960 case CSSValueButtonshadow:
961 return 0xFF888888;
962 case CSSValueButtontext:
963 return 0xFF000000;
964 case CSSValueCaptiontext:
965 return 0xFF000000;
966 case CSSValueGraytext:
967 return 0xFF808080;
968 case CSSValueHighlight:
969 return 0xFFB5D5FF;
970 case CSSValueHighlighttext:
971 return 0xFF000000;
972 case CSSValueInactiveborder:
973 return 0xFFFFFFFF;
974 case CSSValueInactivecaption:
975 return 0xFFFFFFFF;
976 case CSSValueInactivecaptiontext:
977 return 0xFF7F7F7F;
978 case CSSValueInfobackground:
979 return 0xFFFBFCC5;
980 case CSSValueInfotext:
981 return 0xFF000000;
982 case CSSValueMenu:
983 return 0xFFC0C0C0;
984 case CSSValueMenutext:
985 return 0xFF000000;
986 case CSSValueScrollbar:
987 return 0xFFFFFFFF;
988 case CSSValueText:
989 return 0xFF000000;
990 case CSSValueThreeddarkshadow:
991 return 0xFF666666;
992 case CSSValueThreedface:
993 return 0xFFC0C0C0;
994 case CSSValueThreedhighlight:
995 return 0xFFDDDDDD;
996 case CSSValueThreedlightshadow:
997 return 0xFFC0C0C0;
998 case CSSValueThreedshadow:
999 return 0xFF888888;
1000 case CSSValueWindow:
1001 return 0xFFFFFFFF;
1002 case CSSValueWindowframe:
1003 return 0xFFCCCCCC;
1004 case CSSValueWindowtext:
1005 return 0xFF000000;
1006 case CSSValueInternalActiveListBoxSelection:
1007 return activeListBoxSelectionBackgroundColor();
1008 break;
1009 case CSSValueInternalActiveListBoxSelectionText:
1010 return activeListBoxSelectionForegroundColor();
1011 break;
1012 case CSSValueInternalInactiveListBoxSelection:
1013 return inactiveListBoxSelectionBackgroundColor();
1014 break;
1015 case CSSValueInternalInactiveListBoxSelectionText:
1016 return inactiveListBoxSelectionForegroundColor();
1017 break;
1018 default:
1019 break;
1020 }
1021 ASSERT_NOT_REACHED();
1022 return Color();
1023 }
1024
platformActiveTextSearchHighlightColor() const1025 Color RenderTheme::platformActiveTextSearchHighlightColor() const
1026 {
1027 return Color(255, 150, 50); // Orange.
1028 }
1029
platformInactiveTextSearchHighlightColor() const1030 Color RenderTheme::platformInactiveTextSearchHighlightColor() const
1031 {
1032 return Color(255, 255, 0); // Yellow.
1033 }
1034
tapHighlightColor()1035 Color RenderTheme::tapHighlightColor()
1036 {
1037 return theme().platformTapHighlightColor();
1038 }
1039
setCustomFocusRingColor(const Color & c)1040 void RenderTheme::setCustomFocusRingColor(const Color& c)
1041 {
1042 m_customFocusRingColor = c;
1043 m_hasCustomFocusRingColor = true;
1044 }
1045
focusRingColor() const1046 Color RenderTheme::focusRingColor() const
1047 {
1048 return m_hasCustomFocusRingColor ? m_customFocusRingColor : theme().platformFocusRingColor();
1049 }
1050
fileListNameForWidth(Locale & locale,const FileList * fileList,const Font & font,int width) const1051 String RenderTheme::fileListNameForWidth(Locale& locale, const FileList* fileList, const Font& font, int width) const
1052 {
1053 if (width <= 0)
1054 return String();
1055
1056 String string;
1057 if (fileList->isEmpty()) {
1058 string = locale.queryString(WebLocalizedString::FileButtonNoFileSelectedLabel);
1059 } else if (fileList->length() == 1) {
1060 string = fileList->item(0)->name();
1061 } else {
1062 // FIXME: Localization of fileList->length().
1063 return StringTruncator::rightTruncate(locale.queryString(WebLocalizedString::MultipleFileUploadText, String::number(fileList->length())), width, font);
1064 }
1065
1066 return StringTruncator::centerTruncate(string, width, font);
1067 }
1068
shouldOpenPickerWithF4Key() const1069 bool RenderTheme::shouldOpenPickerWithF4Key() const
1070 {
1071 return false;
1072 }
1073
1074 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
supportsCalendarPicker(const AtomicString & type) const1075 bool RenderTheme::supportsCalendarPicker(const AtomicString& type) const
1076 {
1077 return type == InputTypeNames::date
1078 || type == InputTypeNames::datetime
1079 || type == InputTypeNames::datetime_local
1080 || type == InputTypeNames::month
1081 || type == InputTypeNames::week;
1082 }
1083 #endif
1084
shouldUseFallbackTheme(RenderStyle *) const1085 bool RenderTheme::shouldUseFallbackTheme(RenderStyle*) const
1086 {
1087 return false;
1088 }
1089
adjustStyleUsingFallbackTheme(RenderStyle * style,Element * e)1090 void RenderTheme::adjustStyleUsingFallbackTheme(RenderStyle* style, Element* e)
1091 {
1092 ControlPart part = style->appearance();
1093 switch (part) {
1094 case CheckboxPart:
1095 return adjustCheckboxStyleUsingFallbackTheme(style, e);
1096 case RadioPart:
1097 return adjustRadioStyleUsingFallbackTheme(style, e);
1098 default:
1099 break;
1100 }
1101 }
1102
paintUsingFallbackTheme(RenderObject * o,const PaintInfo & i,const IntRect & r)1103 bool RenderTheme::paintUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r)
1104 {
1105 ControlPart part = o->style()->appearance();
1106 switch (part) {
1107 case CheckboxPart:
1108 return paintCheckboxUsingFallbackTheme(o, i, r);
1109 case RadioPart:
1110 return paintRadioUsingFallbackTheme(o, i, r);
1111 default:
1112 break;
1113 }
1114 return true;
1115 }
1116
1117 // static
setSizeIfAuto(RenderStyle * style,const IntSize & size)1118 void RenderTheme::setSizeIfAuto(RenderStyle* style, const IntSize& size)
1119 {
1120 if (style->width().isIntrinsicOrAuto())
1121 style->setWidth(Length(size.width(), Fixed));
1122 if (style->height().isAuto())
1123 style->setHeight(Length(size.height(), Fixed));
1124 }
1125
paintCheckboxUsingFallbackTheme(RenderObject * o,const PaintInfo & i,const IntRect & r)1126 bool RenderTheme::paintCheckboxUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r)
1127 {
1128 WebFallbackThemeEngine::ExtraParams extraParams;
1129 WebCanvas* canvas = i.context->canvas();
1130 extraParams.button.checked = isChecked(o);
1131 extraParams.button.indeterminate = isIndeterminate(o);
1132
1133 float zoomLevel = o->style()->effectiveZoom();
1134 GraphicsContextStateSaver stateSaver(*i.context);
1135 IntRect unzoomedRect = r;
1136 if (zoomLevel != 1) {
1137 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1138 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1139 i.context->translate(unzoomedRect.x(), unzoomedRect.y());
1140 i.context->scale(zoomLevel, zoomLevel);
1141 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1142 }
1143
1144 Platform::current()->fallbackThemeEngine()->paint(canvas, WebFallbackThemeEngine::PartCheckbox, getWebFallbackThemeState(this, o), WebRect(unzoomedRect), &extraParams);
1145 return false;
1146 }
1147
adjustCheckboxStyleUsingFallbackTheme(RenderStyle * style,Element *) const1148 void RenderTheme::adjustCheckboxStyleUsingFallbackTheme(RenderStyle* style, Element*) const
1149 {
1150 // If the width and height are both specified, then we have nothing to do.
1151 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1152 return;
1153
1154 IntSize size = Platform::current()->fallbackThemeEngine()->getSize(WebFallbackThemeEngine::PartCheckbox);
1155 float zoomLevel = style->effectiveZoom();
1156 size.setWidth(size.width() * zoomLevel);
1157 size.setHeight(size.height() * zoomLevel);
1158 setSizeIfAuto(style, size);
1159
1160 // padding - not honored by WinIE, needs to be removed.
1161 style->resetPadding();
1162
1163 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
1164 // for now, we will not honor it.
1165 style->resetBorder();
1166 }
1167
paintRadioUsingFallbackTheme(RenderObject * o,const PaintInfo & i,const IntRect & r)1168 bool RenderTheme::paintRadioUsingFallbackTheme(RenderObject* o, const PaintInfo& i, const IntRect& r)
1169 {
1170 WebFallbackThemeEngine::ExtraParams extraParams;
1171 WebCanvas* canvas = i.context->canvas();
1172 extraParams.button.checked = isChecked(o);
1173 extraParams.button.indeterminate = isIndeterminate(o);
1174
1175 float zoomLevel = o->style()->effectiveZoom();
1176 GraphicsContextStateSaver stateSaver(*i.context);
1177 IntRect unzoomedRect = r;
1178 if (zoomLevel != 1) {
1179 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
1180 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
1181 i.context->translate(unzoomedRect.x(), unzoomedRect.y());
1182 i.context->scale(zoomLevel, zoomLevel);
1183 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
1184 }
1185
1186 Platform::current()->fallbackThemeEngine()->paint(canvas, WebFallbackThemeEngine::PartRadio, getWebFallbackThemeState(this, o), WebRect(unzoomedRect), &extraParams);
1187 return false;
1188 }
1189
adjustRadioStyleUsingFallbackTheme(RenderStyle * style,Element *) const1190 void RenderTheme::adjustRadioStyleUsingFallbackTheme(RenderStyle* style, Element*) const
1191 {
1192 // If the width and height are both specified, then we have nothing to do.
1193 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
1194 return;
1195
1196 IntSize size = Platform::current()->fallbackThemeEngine()->getSize(WebFallbackThemeEngine::PartRadio);
1197 float zoomLevel = style->effectiveZoom();
1198 size.setWidth(size.width() * zoomLevel);
1199 size.setHeight(size.height() * zoomLevel);
1200 setSizeIfAuto(style, size);
1201
1202 // padding - not honored by WinIE, needs to be removed.
1203 style->resetPadding();
1204
1205 // border - honored by WinIE, but looks terrible (just paints in the control box and turns off the Windows XP theme)
1206 // for now, we will not honor it.
1207 style->resetBorder();
1208 }
1209
1210 } // namespace blink
1211