Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / paint / ThemePainter.cpp
blobac2e70f9aaadbba5b8b4869a97180fe6c65500c9
1 /**
2 * This file is part of the theme implementation for form controls in WebCore.
4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Computer, Inc.
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.
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.
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.
22 #include "config.h"
23 #include "core/paint/ThemePainter.h"
25 #include "core/InputTypeNames.h"
26 #include "core/html/HTMLDataListElement.h"
27 #include "core/html/HTMLDataListOptionsCollection.h"
28 #include "core/html/HTMLInputElement.h"
29 #include "core/html/HTMLOptionElement.h"
30 #include "core/html/parser/HTMLParserIdioms.h"
31 #include "core/html/shadow/ShadowElementNames.h"
32 #include "core/layout/LayoutMeter.h"
33 #include "core/layout/LayoutTheme.h"
34 #include "core/layout/LayoutView.h"
35 #include "core/paint/MediaControlsPainter.h"
36 #include "core/paint/PaintInfo.h"
37 #include "core/style/ComputedStyle.h"
38 #include "platform/graphics/GraphicsContextStateSaver.h"
39 #include "public/platform/Platform.h"
40 #include "public/platform/WebFallbackThemeEngine.h"
41 #include "public/platform/WebRect.h"
43 #if USE(NEW_THEME)
44 #include "platform/Theme.h"
45 #endif
47 // The methods in this file are shared by all themes on every platform.
49 namespace blink {
51 static WebFallbackThemeEngine::State getWebFallbackThemeState(const LayoutObject* o)
53 if (!LayoutTheme::isEnabled(o))
54 return WebFallbackThemeEngine::StateDisabled;
55 if (LayoutTheme::isPressed(o))
56 return WebFallbackThemeEngine::StatePressed;
57 if (LayoutTheme::isHovered(o))
58 return WebFallbackThemeEngine::StateHover;
60 return WebFallbackThemeEngine::StateNormal;
63 bool ThemePainter::paint(LayoutObject* o, const PaintInfo& paintInfo, const IntRect& r)
65 ControlPart part = o->styleRef().appearance();
67 if (LayoutTheme::theme().shouldUseFallbackTheme(o->styleRef()))
68 return paintUsingFallbackTheme(o, paintInfo, r);
70 #if USE(NEW_THEME)
71 switch (part) {
72 case CheckboxPart:
73 case RadioPart:
74 case PushButtonPart:
75 case SquareButtonPart:
76 case ButtonPart:
77 case InnerSpinButtonPart:
78 platformTheme()->paint(part, LayoutTheme::controlStatesForLayoutObject(o), const_cast<GraphicsContext*>(paintInfo.context), r, o->styleRef().effectiveZoom(), o->view()->frameView());
79 return false;
80 default:
81 break;
83 #endif
85 // Call the appropriate paint method based off the appearance value.
86 switch (part) {
87 #if !USE(NEW_THEME)
88 case CheckboxPart:
89 return paintCheckbox(o, paintInfo, r);
90 case RadioPart:
91 return paintRadio(o, paintInfo, r);
92 case PushButtonPart:
93 case SquareButtonPart:
94 case ButtonPart:
95 return paintButton(o, paintInfo, r);
96 case InnerSpinButtonPart:
97 return paintInnerSpinButton(o, paintInfo, r);
98 #endif
99 case MenulistPart:
100 return paintMenuList(o, paintInfo, r);
101 case MeterPart:
102 case RelevancyLevelIndicatorPart:
103 case ContinuousCapacityLevelIndicatorPart:
104 case DiscreteCapacityLevelIndicatorPart:
105 case RatingLevelIndicatorPart:
106 return paintMeter(o, paintInfo, r);
107 case ProgressBarPart:
108 return paintProgressBar(o, paintInfo, r);
109 case SliderHorizontalPart:
110 case SliderVerticalPart:
111 return paintSliderTrack(o, paintInfo, r);
112 case SliderThumbHorizontalPart:
113 case SliderThumbVerticalPart:
114 return paintSliderThumb(o, paintInfo, r);
115 case MediaEnterFullscreenButtonPart:
116 case MediaExitFullscreenButtonPart:
117 return MediaControlsPainter::paintMediaFullscreenButton(o, paintInfo, r);
118 case MediaPlayButtonPart:
119 return MediaControlsPainter::paintMediaPlayButton(o, paintInfo, r);
120 case MediaOverlayPlayButtonPart:
121 return MediaControlsPainter::paintMediaOverlayPlayButton(o, paintInfo, r);
122 case MediaMuteButtonPart:
123 return MediaControlsPainter::paintMediaMuteButton(o, paintInfo, r);
124 case MediaToggleClosedCaptionsButtonPart:
125 return MediaControlsPainter::paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
126 case MediaSliderPart:
127 return MediaControlsPainter::paintMediaSlider(o, paintInfo, r);
128 case MediaSliderThumbPart:
129 return MediaControlsPainter::paintMediaSliderThumb(o, paintInfo, r);
130 case MediaVolumeSliderContainerPart:
131 return true;
132 case MediaVolumeSliderPart:
133 return MediaControlsPainter::paintMediaVolumeSlider(o, paintInfo, r);
134 case MediaVolumeSliderThumbPart:
135 return MediaControlsPainter::paintMediaVolumeSliderThumb(o, paintInfo, r);
136 case MediaFullScreenVolumeSliderPart:
137 case MediaFullScreenVolumeSliderThumbPart:
138 case MediaTimeRemainingPart:
139 case MediaCurrentTimePart:
140 case MediaControlsBackgroundPart:
141 return true;
142 case MediaCastOffButtonPart:
143 case MediaOverlayCastOffButtonPart:
144 return MediaControlsPainter::paintMediaCastButton(o, paintInfo, r);
145 case MenulistButtonPart:
146 case TextFieldPart:
147 case TextAreaPart:
148 return true;
149 case SearchFieldPart:
150 return paintSearchField(o, paintInfo, r);
151 case SearchFieldCancelButtonPart:
152 return paintSearchFieldCancelButton(o, paintInfo, r);
153 case SearchFieldDecorationPart:
154 return paintSearchFieldDecoration(o, paintInfo, r);
155 case SearchFieldResultsDecorationPart:
156 return paintSearchFieldResultsDecoration(o, paintInfo, r);
157 default:
158 break;
161 return true; // We don't support the appearance, so let the normal background/border paint.
164 bool ThemePainter::paintBorderOnly(LayoutObject* o, const PaintInfo& paintInfo, const IntRect& r)
166 // Call the appropriate paint method based off the appearance value.
167 switch (o->style()->appearance()) {
168 case TextFieldPart:
169 return paintTextField(o, paintInfo, r);
170 case TextAreaPart:
171 return paintTextArea(o, paintInfo, r);
172 case MenulistButtonPart:
173 case SearchFieldPart:
174 case ListboxPart:
175 return true;
176 case CheckboxPart:
177 case RadioPart:
178 case PushButtonPart:
179 case SquareButtonPart:
180 case ButtonPart:
181 case MenulistPart:
182 case MeterPart:
183 case RelevancyLevelIndicatorPart:
184 case ContinuousCapacityLevelIndicatorPart:
185 case DiscreteCapacityLevelIndicatorPart:
186 case RatingLevelIndicatorPart:
187 case ProgressBarPart:
188 case SliderHorizontalPart:
189 case SliderVerticalPart:
190 case SliderThumbHorizontalPart:
191 case SliderThumbVerticalPart:
192 case SearchFieldCancelButtonPart:
193 case SearchFieldDecorationPart:
194 case SearchFieldResultsDecorationPart:
195 default:
196 break;
199 return false;
202 bool ThemePainter::paintDecorations(LayoutObject* o, const PaintInfo& paintInfo, const IntRect& r)
204 // Call the appropriate paint method based off the appearance value.
205 switch (o->style()->appearance()) {
206 case MenulistButtonPart:
207 return paintMenuListButton(o, paintInfo, r);
208 case TextFieldPart:
209 case TextAreaPart:
210 case CheckboxPart:
211 case RadioPart:
212 case PushButtonPart:
213 case SquareButtonPart:
214 case ButtonPart:
215 case MenulistPart:
216 case MeterPart:
217 case RelevancyLevelIndicatorPart:
218 case ContinuousCapacityLevelIndicatorPart:
219 case DiscreteCapacityLevelIndicatorPart:
220 case RatingLevelIndicatorPart:
221 case ProgressBarPart:
222 case SliderHorizontalPart:
223 case SliderVerticalPart:
224 case SliderThumbHorizontalPart:
225 case SliderThumbVerticalPart:
226 case SearchFieldPart:
227 case SearchFieldCancelButtonPart:
228 case SearchFieldDecorationPart:
229 case SearchFieldResultsDecorationPart:
230 default:
231 break;
234 return false;
237 bool ThemePainter::paintMeter(LayoutObject*, const PaintInfo&, const IntRect&)
239 return true;
242 void ThemePainter::paintSliderTicks(LayoutObject* o, const PaintInfo& paintInfo, const IntRect& rect)
244 Node* node = o->node();
245 if (!isHTMLInputElement(node))
246 return;
248 HTMLInputElement* input = toHTMLInputElement(node);
249 if (input->type() != InputTypeNames::range)
250 return;
252 HTMLDataListElement* dataList = input->dataList();
253 if (!dataList)
254 return;
256 double min = input->minimum();
257 double max = input->maximum();
258 ControlPart part = o->style()->appearance();
259 // We don't support ticks on alternate sliders like MediaVolumeSliders.
260 if (part != SliderHorizontalPart && part != SliderVerticalPart)
261 return;
262 bool isHorizontal = part == SliderHorizontalPart;
264 IntSize thumbSize;
265 LayoutObject* thumbLayoutObject = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderThumb())->layoutObject();
266 if (thumbLayoutObject) {
267 const ComputedStyle& thumbStyle = thumbLayoutObject->styleRef();
268 int thumbWidth = thumbStyle.width().intValue();
269 int thumbHeight = thumbStyle.height().intValue();
270 thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
271 thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
274 IntSize tickSize = LayoutTheme::theme().sliderTickSize();
275 float zoomFactor = o->style()->effectiveZoom();
276 FloatRect tickRect;
277 int tickRegionSideMargin = 0;
278 int tickRegionWidth = 0;
279 IntRect trackBounds;
280 LayoutObject* trackLayoutObject = input->userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack())->layoutObject();
281 // We can ignoring transforms because transform is handled by the graphics context.
282 if (trackLayoutObject)
283 trackBounds = trackLayoutObject->absoluteBoundingBoxRectIgnoringTransforms();
284 IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms();
286 // Make position relative to the transformed ancestor element.
287 trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
288 trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
290 if (isHorizontal) {
291 tickRect.setWidth(floor(tickSize.width() * zoomFactor));
292 tickRect.setHeight(floor(tickSize.height() * zoomFactor));
293 tickRect.setY(floor(rect.y() + rect.height() / 2.0 + LayoutTheme::theme().sliderTickOffsetFromTrackCenter() * zoomFactor));
294 tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
295 tickRegionWidth = trackBounds.width() - thumbSize.width();
296 } else {
297 tickRect.setWidth(floor(tickSize.height() * zoomFactor));
298 tickRect.setHeight(floor(tickSize.width() * zoomFactor));
299 tickRect.setX(floor(rect.x() + rect.width() / 2.0 + LayoutTheme::theme().sliderTickOffsetFromTrackCenter() * zoomFactor));
300 tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
301 tickRegionWidth = trackBounds.height() - thumbSize.width();
303 RefPtrWillBeRawPtr<HTMLDataListOptionsCollection> options = dataList->options();
304 for (unsigned i = 0; HTMLOptionElement* optionElement = options->item(i); i++) {
305 String value = optionElement->value();
306 if (!input->isValidValue(value))
307 continue;
308 double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
309 double tickFraction = (parsedValue - min) / (max - min);
310 double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
311 double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
312 if (isHorizontal)
313 tickRect.setX(tickPosition);
314 else
315 tickRect.setY(tickPosition);
316 paintInfo.context->fillRect(tickRect, o->resolveColor(CSSPropertyColor));
320 bool ThemePainter::paintUsingFallbackTheme(LayoutObject* o, const PaintInfo& i, const IntRect& r)
322 ControlPart part = o->style()->appearance();
323 switch (part) {
324 case CheckboxPart:
325 return paintCheckboxUsingFallbackTheme(o, i, r);
326 case RadioPart:
327 return paintRadioUsingFallbackTheme(o, i, r);
328 default:
329 break;
331 return true;
334 bool ThemePainter::paintCheckboxUsingFallbackTheme(LayoutObject* o, const PaintInfo& i, const IntRect& r)
336 WebFallbackThemeEngine::ExtraParams extraParams;
337 WebCanvas* canvas = i.context->canvas();
338 extraParams.button.checked = LayoutTheme::isChecked(o);
339 extraParams.button.indeterminate = LayoutTheme::isIndeterminate(o);
341 float zoomLevel = o->style()->effectiveZoom();
342 GraphicsContextStateSaver stateSaver(*i.context);
343 IntRect unzoomedRect = r;
344 if (zoomLevel != 1) {
345 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
346 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
347 i.context->translate(unzoomedRect.x(), unzoomedRect.y());
348 i.context->scale(zoomLevel, zoomLevel);
349 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
352 Platform::current()->fallbackThemeEngine()->paint(canvas, WebFallbackThemeEngine::PartCheckbox, getWebFallbackThemeState(o), WebRect(unzoomedRect), &extraParams);
353 return false;
356 bool ThemePainter::paintRadioUsingFallbackTheme(LayoutObject* o, const PaintInfo& i, const IntRect& r)
358 WebFallbackThemeEngine::ExtraParams extraParams;
359 WebCanvas* canvas = i.context->canvas();
360 extraParams.button.checked = LayoutTheme::isChecked(o);
361 extraParams.button.indeterminate = LayoutTheme::isIndeterminate(o);
363 float zoomLevel = o->style()->effectiveZoom();
364 GraphicsContextStateSaver stateSaver(*i.context);
365 IntRect unzoomedRect = r;
366 if (zoomLevel != 1) {
367 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
368 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
369 i.context->translate(unzoomedRect.x(), unzoomedRect.y());
370 i.context->scale(zoomLevel, zoomLevel);
371 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
374 Platform::current()->fallbackThemeEngine()->paint(canvas, WebFallbackThemeEngine::PartRadio, getWebFallbackThemeState(o), WebRect(unzoomedRect), &extraParams);
375 return false;
378 } // namespace blink