2 * Copyright (C) 2007 Apple Inc.
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4 * Copyright (C) 2008 Collabora Ltd.
5 * Copyright (C) 2008, 2009 Google Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
25 #include "RenderThemeChromiumSkia.h"
27 #include "CSSValueKeywords.h"
28 #include "CurrentTime.h"
29 #include "GraphicsContext.h"
30 #include "HTMLMediaElement.h"
31 #include "HTMLNames.h"
33 #include "MediaControlElements.h"
34 #include "PaintInfo.h"
35 #include "PlatformBridge.h"
36 #include "PlatformContextSkia.h"
37 #include "RenderBox.h"
38 #include "RenderMediaControlsChromium.h"
39 #include "RenderObject.h"
40 #include "RenderProgress.h"
41 #include "RenderSlider.h"
42 #include "ScrollbarTheme.h"
43 #include "TimeRanges.h"
44 #include "TransformationMatrix.h"
45 #include "UserAgentStyleSheets.h"
48 #include "SkGradientShader.h"
59 static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
61 // These values all match Safari/Win.
62 static const float defaultControlFontPixelSize = 13;
63 static const float defaultCancelButtonSize = 9;
64 static const float minCancelButtonSize = 5;
65 static const float maxCancelButtonSize = 21;
66 static const float defaultSearchFieldResultsDecorationSize = 13;
67 static const float minSearchFieldResultsDecorationSize = 9;
68 static const float maxSearchFieldResultsDecorationSize = 30;
69 static const float defaultSearchFieldResultsButtonWidth = 18;
71 static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
73 if (style->width().isIntrinsicOrAuto())
74 style->setWidth(Length(size.width(), Fixed));
75 if (style->height().isAuto())
76 style->setHeight(Length(size.height(), Fixed));
79 static void drawVertLine(SkCanvas* canvas, int x, int y1, int y2, const SkPaint& paint)
82 skrect.set(x, y1, x + 1, y2 + 1);
83 canvas->drawIRect(skrect, paint);
86 static void drawHorizLine(SkCanvas* canvas, int x1, int x2, int y, const SkPaint& paint)
89 skrect.set(x1, y, x2 + 1, y + 1);
90 canvas->drawIRect(skrect, paint);
93 static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint)
95 const int right = rect.x() + rect.width() - 1;
96 const int bottom = rect.y() + rect.height() - 1;
97 drawHorizLine(canvas, rect.x(), right, rect.y(), paint);
98 drawVertLine(canvas, right, rect.y(), bottom, paint);
99 drawHorizLine(canvas, rect.x(), right, bottom, paint);
100 drawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
103 // We aim to match IE here.
104 // -IE uses a font based on the encoding as the default font for form controls.
105 // -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
106 // which returns MS Shell Dlg)
107 // -Safari uses Lucida Grande.
109 // FIXME: The only case where we know we don't match IE is for ANSI encodings.
110 // IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
111 // sizes (e.g. 15px). So, for now we just use Arial.
112 const String& RenderThemeChromiumSkia::defaultGUIFont()
114 DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
118 float RenderThemeChromiumSkia::defaultFontSize = 16.0;
120 RenderThemeChromiumSkia::RenderThemeChromiumSkia()
124 RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
128 // Use the Windows style sheets to match their metrics.
129 String RenderThemeChromiumSkia::extraDefaultStyleSheet()
131 return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) +
132 String(themeChromiumSkiaUserAgentStyleSheet, sizeof(themeChromiumSkiaUserAgentStyleSheet));
135 String RenderThemeChromiumSkia::extraQuirksStyleSheet()
137 return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
141 String RenderThemeChromiumSkia::extraMediaControlsStyleSheet()
143 return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
147 bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
152 bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
154 // This causes WebKit to draw the focus rings for us.
158 Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
160 return Color(0x1e, 0x90, 0xff);
163 Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
165 return Color(0xc8, 0xc8, 0xc8);
168 Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
173 Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
175 return Color(0x32, 0x32, 0x32);
178 Color RenderThemeChromiumSkia::platformFocusRingColor() const
180 static Color focusRingColor(229, 151, 0, 255);
181 return focusRingColor;
184 double RenderThemeChromiumSkia::caretBlinkInterval() const
186 // Disable the blinking caret in layout test mode, as it introduces
187 // a race condition for the pixel tests. http://b/1198440
188 if (PlatformBridge::layoutTestMode())
191 return caretBlinkIntervalInternal();
194 void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
196 float fontSize = defaultFontSize;
199 case CSSValueWebkitMiniControl:
200 case CSSValueWebkitSmallControl:
201 case CSSValueWebkitControl:
202 // Why 2 points smaller? Because that's what Gecko does. Note that we
203 // are assuming a 96dpi screen, which is the default that we use on
205 static const float pointsPerInch = 72.0f;
206 static const float pixelsPerInch = 96.0f;
207 fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
211 fontDescription.firstFamily().setFamily(defaultGUIFont());
212 fontDescription.setSpecifiedSize(fontSize);
213 fontDescription.setIsAbsoluteSize(true);
214 fontDescription.setGenericFamily(FontDescription::NoFamily);
215 fontDescription.setWeight(FontWeightNormal);
216 fontDescription.setItalic(false);
219 int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
224 // These are the default dimensions of radio buttons and checkboxes.
225 static const int widgetStandardWidth = 13;
226 static const int widgetStandardHeight = 13;
228 // Return a rectangle that has the same center point as |original|, but with a
229 // size capped at |width| by |height|.
230 IntRect center(const IntRect& original, int width, int height)
232 width = std::min(original.width(), width);
233 height = std::min(original.height(), height);
234 int x = original.x() + (original.width() - width) / 2;
235 int y = original.y() + (original.height() - height) / 2;
237 return IntRect(x, y, width, height);
240 bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
242 static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef();
243 static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef();
244 static Image* const indeterminateImage = Image::loadPlatformResource("linuxCheckboxIndeterminate").releaseRef();
245 static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOn").releaseRef();
246 static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOff").releaseRef();
247 static Image* const disabledIndeterminateImage = Image::loadPlatformResource("linuxCheckboxDisabledIndeterminate").releaseRef();
251 if (isIndeterminate(o))
252 image = isEnabled(o) ? indeterminateImage : disabledIndeterminateImage;
253 else if (isChecked(o))
254 image = isEnabled(o) ? checkedImage : disabledCheckedImage;
256 image = isEnabled(o) ? uncheckedImage : disabledUncheckedImage;
258 i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth));
262 void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const
264 // If the width and height are both specified, then we have nothing to do.
265 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
268 // FIXME: A hard-coded size of 13 is used. This is wrong but necessary
269 // for now. It matches Firefox. At different DPI settings on Windows,
270 // querying the theme gives you a larger size that accounts for the higher
271 // DPI. Until our entire engine honors a DPI setting other than 96, we
272 // can't rely on the theme's metrics.
273 const IntSize size(widgetStandardHeight, widgetStandardWidth);
274 setSizeIfAuto(style, size);
277 bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
279 static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef();
280 static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef();
281 static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxRadioDisabledOn").releaseRef();
282 static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxRadioDisabledOff").releaseRef();
285 if (this->isEnabled(o))
286 image = this->isChecked(o) ? checkedImage : uncheckedImage;
288 image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage;
290 i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth));
294 void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
296 // Use same sizing for radio box as checkbox.
297 setCheckboxSize(style);
300 static SkColor brightenColor(double h, double s, double l, float brightenAmount)
308 return makeRGBAFromHSLA(h, s, l, 1.0);
311 static void paintButtonLike(RenderTheme* theme, RenderObject* o, const PaintInfo& i, const IntRect& rect)
313 SkCanvas* const canvas = i.context->platformContext()->canvas();
316 const int right = rect.x() + rect.width();
317 const int bottom = rect.y() + rect.height();
318 SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd);
319 if (o->hasBackground())
320 baseColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
322 Color(baseColor).getHSL(h, s, l);
323 // Our standard gradient is from 0xdd to 0xf8. This is the amount of
324 // increased luminance between those values.
325 SkColor lightColor(brightenColor(h, s, l, 0.105));
327 // If the button is too small, fallback to drawing a single, solid color
328 if (rect.width() < 5 || rect.height() < 5) {
329 paint.setColor(baseColor);
330 skrect.set(rect.x(), rect.y(), right, bottom);
331 canvas->drawRect(skrect, paint);
335 const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55;
336 paint.setARGB(borderAlpha, 0, 0, 0);
337 canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint);
338 canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint);
339 canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint);
340 canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint);
342 paint.setColor(SK_ColorBLACK);
344 const int lightEnd = theme->isPressed(o) ? 1 : 0;
345 const int darkEnd = !lightEnd;
346 p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
347 p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1));
349 colors[0] = lightColor;
350 colors[1] = baseColor;
352 SkShader* shader = SkGradientShader::CreateLinear(
353 p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
354 paint.setStyle(SkPaint::kFill_Style);
355 paint.setShader(shader);
358 skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1);
359 canvas->drawRect(skrect, paint);
361 paint.setShader(NULL);
362 paint.setColor(brightenColor(h, s, l, -0.0588));
363 canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
364 canvas->drawPoint(right - 2, rect.y() + 1, paint);
365 canvas->drawPoint(rect.x() + 1, bottom - 2, paint);
366 canvas->drawPoint(right - 2, bottom - 2, paint);
369 bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
371 paintButtonLike(this, o, i, rect);
375 void RenderThemeChromiumSkia::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
377 if (style->appearance() == PushButtonPart) {
378 // Ignore line-height.
379 style->setLineHeight(RenderStyle::initialLineHeight());
384 bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
389 bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
391 return paintTextField(o, i, r);
394 void RenderThemeChromiumSkia::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
396 // Ignore line-height.
397 style->setLineHeight(RenderStyle::initialLineHeight());
400 bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& r)
402 return paintTextField(o, i, r);
405 void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
407 // Scale the button size based on the font size
408 float fontScale = style->fontSize() / defaultControlFontPixelSize;
409 int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
410 style->setWidth(Length(cancelButtonSize, Fixed));
411 style->setHeight(Length(cancelButtonSize, Fixed));
414 IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, IntRect partRect, const IntRect& localOffset) const
416 // Compute an offset between the part renderer and the input renderer.
417 IntSize offsetFromInputRenderer = -(partRenderer->offsetFromAncestorContainer(inputRenderer));
418 // Move the rect into partRenderer's coords.
419 partRect.move(offsetFromInputRenderer);
420 // Account for the local drawing offset.
421 partRect.move(localOffset.x(), localOffset.y());
426 bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
428 // Get the renderer of <input> element.
429 Node* input = cancelButtonObject->node()->shadowAncestorNode();
430 if (!input->renderer()->isBox())
432 RenderBox* inputRenderBox = toRenderBox(input->renderer());
433 IntRect inputContentBox = inputRenderBox->contentBoxRect();
435 // Make sure the scaled button stays square and will fit in its parent's box.
436 int cancelButtonSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height()));
437 // Calculate cancel button's coordinates relative to the input element.
438 // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
439 // be one pixel closer to the bottom of the field. This tends to look better with the text.
440 IntRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
441 inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
442 cancelButtonSize, cancelButtonSize);
443 IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
445 static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
446 static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
447 paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage,
448 cancelButtonObject->style()->colorSpace(), paintingRect);
452 void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
454 IntSize emptySize(1, 11);
455 style->setWidth(Length(emptySize.width(), Fixed));
456 style->setHeight(Length(emptySize.height(), Fixed));
459 void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
461 // Scale the decoration size based on the font size
462 float fontScale = style->fontSize() / defaultControlFontPixelSize;
463 int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
464 maxSearchFieldResultsDecorationSize));
465 style->setWidth(Length(magnifierSize, Fixed));
466 style->setHeight(Length(magnifierSize, Fixed));
469 bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
471 // Get the renderer of <input> element.
472 Node* input = magnifierObject->node()->shadowAncestorNode();
473 if (!input->renderer()->isBox())
475 RenderBox* inputRenderBox = toRenderBox(input->renderer());
476 IntRect inputContentBox = inputRenderBox->contentBoxRect();
478 // Make sure the scaled decoration stays square and will fit in its parent's box.
479 int magnifierSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height()));
480 // Calculate decoration's coordinates relative to the input element.
481 // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
482 // be one pixel closer to the bottom of the field. This tends to look better with the text.
483 IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
484 inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2,
485 magnifierSize, magnifierSize);
486 IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
488 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
489 paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
493 void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
495 // Scale the button size based on the font size
496 float fontScale = style->fontSize() / defaultControlFontPixelSize;
497 int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
498 maxSearchFieldResultsDecorationSize));
499 int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
500 style->setWidth(Length(magnifierWidth, Fixed));
501 style->setHeight(Length(magnifierHeight, Fixed));
504 bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
506 // Get the renderer of <input> element.
507 Node* input = magnifierObject->node()->shadowAncestorNode();
508 if (!input->renderer()->isBox())
510 RenderBox* inputRenderBox = toRenderBox(input->renderer());
511 IntRect inputContentBox = inputRenderBox->contentBoxRect();
513 // Make sure the scaled decoration will fit in its parent's box.
514 int magnifierHeight = std::min(inputContentBox.height(), r.height());
515 int magnifierWidth = std::min(inputContentBox.width(), static_cast<int>(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize));
516 IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
517 inputContentBox.y() + (inputContentBox.height() - magnifierHeight + 1) / 2,
518 magnifierWidth, magnifierHeight);
519 IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
521 static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
522 paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
526 bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
529 return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect);
531 UNUSED_PARAM(object);
532 UNUSED_PARAM(paintInfo);
538 bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
541 return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
543 UNUSED_PARAM(object);
544 UNUSED_PARAM(paintInfo);
550 bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
553 return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
555 UNUSED_PARAM(object);
556 UNUSED_PARAM(paintInfo);
562 void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const
565 RenderMediaControlsChromium::adjustMediaSliderThumbSize(object);
567 UNUSED_PARAM(object);
571 bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
574 return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
576 UNUSED_PARAM(object);
577 UNUSED_PARAM(paintInfo);
583 bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
586 return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
588 UNUSED_PARAM(object);
589 UNUSED_PARAM(paintInfo);
595 bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
598 return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
600 UNUSED_PARAM(object);
601 UNUSED_PARAM(paintInfo);
607 bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
610 return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
612 UNUSED_PARAM(object);
613 UNUSED_PARAM(paintInfo);
619 void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
621 // Height is locked to auto on all browsers.
622 style->setLineHeight(RenderStyle::initialLineHeight());
625 bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
627 SkCanvas* const canvas = i.context->platformContext()->canvas();
628 const int right = rect.x() + rect.width();
629 const int middle = rect.y() + rect.height() / 2;
631 paintButtonLike(this, o, i, rect);
634 paint.setColor(SK_ColorBLACK);
635 paint.setAntiAlias(true);
636 paint.setStyle(SkPaint::kFill_Style);
638 int arrowXPosition = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
640 path.moveTo(arrowXPosition, middle - 3);
644 canvas->drawPath(path, paint);
649 void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
651 adjustMenuListStyle(selector, style, e);
654 // Used to paint styled menulists (i.e. with a non-default border)
655 bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
657 return paintMenuList(o, i, rect);
660 bool RenderThemeChromiumSkia::paintSliderTrack(RenderObject*, const PaintInfo& i, const IntRect& rect)
662 // Just paint a grey box for now (matches the color of a scrollbar background.
663 SkCanvas* const canvas = i.context->platformContext()->canvas();
664 int verticalCenter = rect.y() + rect.height() / 2;
665 int top = std::max(rect.y(), verticalCenter - 2);
666 int bottom = std::min(rect.y() + rect.height(), verticalCenter + 2);
669 const SkColor grey = SkColorSetARGB(0xff, 0xe3, 0xdd, 0xd8);
670 paint.setColor(grey);
673 skrect.set(rect.x(), top, rect.x() + rect.width(), bottom);
674 canvas->drawRect(skrect, paint);
679 bool RenderThemeChromiumSkia::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
681 // Make a thumb similar to the scrollbar thumb.
682 const bool hovered = isHovered(o) || toRenderSlider(o->parent())->inDragMode();
683 const int midx = rect.x() + rect.width() / 2;
684 const int midy = rect.y() + rect.height() / 2;
685 const bool vertical = (o->style()->appearance() == SliderThumbVerticalPart);
686 SkCanvas* const canvas = i.context->platformContext()->canvas();
688 const SkColor thumbLightGrey = SkColorSetARGB(0xff, 0xf4, 0xf2, 0xef);
689 const SkColor thumbDarkGrey = SkColorSetARGB(0xff, 0xea, 0xe5, 0xe0);
691 paint.setColor(hovered ? SK_ColorWHITE : thumbLightGrey);
695 skrect.set(rect.x(), rect.y(), midx + 1, rect.bottom());
697 skrect.set(rect.x(), rect.y(), rect.right(), midy + 1);
699 canvas->drawIRect(skrect, paint);
701 paint.setColor(hovered ? thumbLightGrey : thumbDarkGrey);
704 skrect.set(midx + 1, rect.y(), rect.right(), rect.bottom());
706 skrect.set(rect.x(), midy + 1, rect.right(), rect.bottom());
708 canvas->drawIRect(skrect, paint);
710 const SkColor borderDarkGrey = SkColorSetARGB(0xff, 0x9d, 0x96, 0x8e);
711 paint.setColor(borderDarkGrey);
712 drawBox(canvas, rect, paint);
714 if (rect.height() > 10 && rect.width() > 10) {
715 drawHorizLine(canvas, midx - 2, midx + 2, midy, paint);
716 drawHorizLine(canvas, midx - 2, midx + 2, midy - 3, paint);
717 drawHorizLine(canvas, midx - 2, midx + 2, midy + 3, paint);
723 int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
725 return menuListInternalPadding(style, LeftPadding);
728 int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
730 return menuListInternalPadding(style, RightPadding);
733 int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
735 return menuListInternalPadding(style, TopPadding);
738 int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
740 return menuListInternalPadding(style, BottomPadding);
744 bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e)
746 return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e);
751 void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
753 defaultFontSize = static_cast<float>(fontSize);
756 double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
758 return RenderTheme::caretBlinkInterval();
761 int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
763 // This internal padding is in addition to the user-supplied padding.
764 // Matches the FF behavior.
765 int padding = styledMenuListInternalPadding[paddingType];
767 // Reserve the space for right arrow here. The rest of the padding is
768 // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
769 // RenderMenuList to lay out the individual items in the popup.
770 // If the MenuList actually has appearance "NoAppearance", then that means
771 // we don't draw a button, so don't reserve space for it.
772 const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
773 if (paddingType == barType && style->appearance() != NoControlPart)
774 padding += ScrollbarTheme::nativeTheme()->scrollbarThickness();
779 #if ENABLE(PROGRESS_TAG)
782 // Following values are come from default of GTK+
784 static const int progressDeltaPixelsPerSecond = 100;
785 static const int progressActivityBlocks = 5;
786 static const int progressAnimationFrmaes = 10;
787 static const double progressAnimationInterval = 0.125;
789 IntRect RenderThemeChromiumSkia::determinateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
791 int dx = rect.width() * renderProgress->position();
792 if (renderProgress->style()->direction() == RTL)
793 return IntRect(rect.x() + rect.width() - dx, rect.y(), dx, rect.height());
794 return IntRect(rect.x(), rect.y(), dx, rect.height());
797 IntRect RenderThemeChromiumSkia::indeterminateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
800 int valueWidth = rect.width() / progressActivityBlocks;
801 int movableWidth = rect.width() - valueWidth;
802 if (movableWidth <= 0)
805 double progress = renderProgress->animationProgress();
807 return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWidth, rect.height());
808 return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), valueWidth, rect.height());
811 double RenderThemeChromiumSkia::animationRepeatIntervalForProgressBar(RenderProgress*) const
813 return progressAnimationInterval;
816 double RenderThemeChromiumSkia::animationDurationForProgressBar(RenderProgress* renderProgress) const
818 return progressAnimationInterval * progressAnimationFrmaes * 2; // "2" for back and forth
821 bool RenderThemeChromiumSkia::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
823 static Image* barImage = Image::loadPlatformResource("linuxProgressBar").releaseRef();
824 static Image* valueImage = Image::loadPlatformResource("linuxProgressValue").releaseRef();
825 static Image* leftBorderImage = Image::loadPlatformResource("linuxProgressBorderLeft").releaseRef();
826 static Image* rightBorderImage = Image::loadPlatformResource("linuxProgressBorderRight").releaseRef();
827 ASSERT(barImage->height() == valueImage->height());
829 if (!renderObject->isProgress())
832 paintInfo.context->platformContext()->setImageResamplingHint(barImage->size(), rect.size());
834 RenderProgress* renderProgress = toRenderProgress(renderObject);
835 double tileScale = static_cast<double>(rect.height()) / barImage->height();
836 IntSize barTileSize(static_cast<int>(barImage->width() * tileScale), rect.height());
837 ColorSpace colorSpace = renderObject->style()->colorSpace();
839 paintInfo.context->drawTiledImage(barImage, colorSpace, rect, IntPoint(0, 0), barTileSize);
841 IntRect valueRect = progressValueRectFor(renderProgress, rect);
842 if (valueRect.width()) {
844 IntSize valueTileSize(std::max(1, static_cast<int>(valueImage->width() * tileScale)), valueRect.height());
846 int leftOffset = valueRect.x() - rect.x();
847 int roundedLeftOffset= (leftOffset / valueTileSize.width()) * valueTileSize.width();
848 int dstLeftValueWidth = roundedLeftOffset - leftOffset + (leftOffset % valueImage->width()) ? valueTileSize.width() : 0;
850 IntRect dstLeftValueRect(valueRect.x(), valueRect.y(), dstLeftValueWidth, valueRect.height());
851 int srcLeftValueWidth = dstLeftValueWidth / tileScale;
852 IntRect srcLeftValueRect(valueImage->width() - srcLeftValueWidth, 0, srcLeftValueWidth, valueImage->height());
853 paintInfo.context->drawImage(valueImage, colorSpace, dstLeftValueRect, srcLeftValueRect);
855 int rightOffset = valueRect.right() - rect.x();
856 int roundedRightOffset = (rightOffset / valueTileSize.width()) * valueTileSize.width();
857 int dstRightValueWidth = rightOffset - roundedRightOffset;
858 IntRect dstRightValueRect(rect.x() + roundedRightOffset, valueRect.y(), dstRightValueWidth, valueTileSize.height());
859 int srcRightValueWidth = dstRightValueWidth / tileScale;
860 IntRect srcRightValueRect(0, 0, srcRightValueWidth, valueImage->height());
861 paintInfo.context->drawImage(valueImage, colorSpace, dstRightValueRect, srcRightValueRect);
863 IntRect alignedValueRect(dstLeftValueRect.right(), dstLeftValueRect.y(),
864 dstRightValueRect.x() - dstLeftValueRect.right(), dstLeftValueRect.height());
865 paintInfo.context->drawTiledImage(valueImage, colorSpace, alignedValueRect, IntPoint(0, 0), valueTileSize);
868 int dstLeftBorderWidth = leftBorderImage->width() * tileScale;
869 IntRect dstLeftBorderRect(rect.x(), rect.y(), dstLeftBorderWidth, rect.height());
870 paintInfo.context->drawImage(leftBorderImage, colorSpace, dstLeftBorderRect, leftBorderImage->rect());
872 int dstRightBorderWidth = rightBorderImage->width() * tileScale;
873 IntRect dstRightBorderRect(rect.right() - dstRightBorderWidth, rect.y(), dstRightBorderWidth, rect.height());
874 paintInfo.context->drawImage(rightBorderImage, colorSpace, dstRightBorderRect, rightBorderImage->rect());
876 paintInfo.context->platformContext()->clearImageResamplingHint();
882 IntRect RenderThemeChromiumSkia::progressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
884 return renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, rect) : indeterminateProgressValueRectFor(renderProgress, rect);
889 } // namespace WebCore