summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderThemeChromiumSkia.cpp')
-rw-r--r--Source/WebCore/rendering/RenderThemeChromiumSkia.cpp888
1 files changed, 888 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
new file mode 100644
index 0000000..9824851
--- /dev/null
+++ b/Source/WebCore/rendering/RenderThemeChromiumSkia.cpp
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderThemeChromiumSkia.h"
+
+#include "ChromiumBridge.h"
+#include "CSSValueKeywords.h"
+#include "CurrentTime.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+#include "Image.h"
+#include "MediaControlElements.h"
+#include "PlatformContextSkia.h"
+#include "RenderBox.h"
+#include "RenderMediaControlsChromium.h"
+#include "RenderObject.h"
+#include "RenderProgress.h"
+#include "RenderSlider.h"
+#include "ScrollbarTheme.h"
+#include "TimeRanges.h"
+#include "TransformationMatrix.h"
+#include "UserAgentStyleSheets.h"
+
+#include "SkShader.h"
+#include "SkGradientShader.h"
+
+namespace WebCore {
+
+enum PaddingType {
+ TopPadding,
+ RightPadding,
+ BottomPadding,
+ LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// These values all match Safari/Win.
+static const float defaultControlFontPixelSize = 13;
+static const float defaultCancelButtonSize = 9;
+static const float minCancelButtonSize = 5;
+static const float maxCancelButtonSize = 21;
+static const float defaultSearchFieldResultsDecorationSize = 13;
+static const float minSearchFieldResultsDecorationSize = 9;
+static const float maxSearchFieldResultsDecorationSize = 30;
+static const float defaultSearchFieldResultsButtonWidth = 18;
+
+static void setSizeIfAuto(RenderStyle* style, const IntSize& size)
+{
+ if (style->width().isIntrinsicOrAuto())
+ style->setWidth(Length(size.width(), Fixed));
+ if (style->height().isAuto())
+ style->setHeight(Length(size.height(), Fixed));
+}
+
+static void drawVertLine(SkCanvas* canvas, int x, int y1, int y2, const SkPaint& paint)
+{
+ SkIRect skrect;
+ skrect.set(x, y1, x + 1, y2 + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+static void drawHorizLine(SkCanvas* canvas, int x1, int x2, int y, const SkPaint& paint)
+{
+ SkIRect skrect;
+ skrect.set(x1, y, x2 + 1, y + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+static void drawBox(SkCanvas* canvas, const IntRect& rect, const SkPaint& paint)
+{
+ const int right = rect.x() + rect.width() - 1;
+ const int bottom = rect.y() + rect.height() - 1;
+ drawHorizLine(canvas, rect.x(), right, rect.y(), paint);
+ drawVertLine(canvas, right, rect.y(), bottom, paint);
+ drawHorizLine(canvas, rect.x(), right, bottom, paint);
+ drawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
+}
+
+// We aim to match IE here.
+// -IE uses a font based on the encoding as the default font for form controls.
+// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
+// which returns MS Shell Dlg)
+// -Safari uses Lucida Grande.
+//
+// FIXME: The only case where we know we don't match IE is for ANSI encodings.
+// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
+// sizes (e.g. 15px). So, for now we just use Arial.
+const String& RenderThemeChromiumSkia::defaultGUIFont()
+{
+ DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
+ return fontFace;
+}
+
+float RenderThemeChromiumSkia::defaultFontSize = 16.0;
+
+RenderThemeChromiumSkia::RenderThemeChromiumSkia()
+{
+}
+
+RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
+{
+}
+
+// Use the Windows style sheets to match their metrics.
+String RenderThemeChromiumSkia::extraDefaultStyleSheet()
+{
+ return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) +
+ String(themeChromiumSkiaUserAgentStyleSheet, sizeof(themeChromiumSkiaUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumSkia::extraQuirksStyleSheet()
+{
+ return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+#if ENABLE(VIDEO)
+String RenderThemeChromiumSkia::extraMediaControlsStyleSheet()
+{
+ return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
+}
+#endif
+
+bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
+{
+ // This causes WebKit to draw the focus rings for us.
+ return false;
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
+{
+ return Color(0x1e, 0x90, 0xff);
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
+{
+ return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
+{
+ return Color::black;
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
+{
+ return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumSkia::platformFocusRingColor() const
+{
+ static Color focusRingColor(229, 151, 0, 255);
+ return focusRingColor;
+}
+
+double RenderThemeChromiumSkia::caretBlinkInterval() const
+{
+ // Disable the blinking caret in layout test mode, as it introduces
+ // a race condition for the pixel tests. http://b/1198440
+ if (ChromiumBridge::layoutTestMode())
+ return 0;
+
+ return caretBlinkIntervalInternal();
+}
+
+void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
+{
+ float fontSize = defaultFontSize;
+
+ switch (propId) {
+ case CSSValueWebkitMiniControl:
+ case CSSValueWebkitSmallControl:
+ case CSSValueWebkitControl:
+ // Why 2 points smaller? Because that's what Gecko does. Note that we
+ // are assuming a 96dpi screen, which is the default that we use on
+ // Windows.
+ static const float pointsPerInch = 72.0f;
+ static const float pixelsPerInch = 96.0f;
+ fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
+ break;
+ }
+
+ fontDescription.firstFamily().setFamily(defaultGUIFont());
+ fontDescription.setSpecifiedSize(fontSize);
+ fontDescription.setIsAbsoluteSize(true);
+ fontDescription.setGenericFamily(FontDescription::NoFamily);
+ fontDescription.setWeight(FontWeightNormal);
+ fontDescription.setItalic(false);
+}
+
+int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
+{
+ return 0;
+}
+
+// These are the default dimensions of radio buttons and checkboxes.
+static const int widgetStandardWidth = 13;
+static const int widgetStandardHeight = 13;
+
+// Return a rectangle that has the same center point as |original|, but with a
+// size capped at |width| by |height|.
+IntRect center(const IntRect& original, int width, int height)
+{
+ width = std::min(original.width(), width);
+ height = std::min(original.height(), height);
+ int x = original.x() + (original.width() - width) / 2;
+ int y = original.y() + (original.height() - height) / 2;
+
+ return IntRect(x, y, width, height);
+}
+
+bool RenderThemeChromiumSkia::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxCheckboxOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxCheckboxOff").releaseRef();
+ static Image* const indeterminateImage = Image::loadPlatformResource("linuxCheckboxIndeterminate").releaseRef();
+ static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOn").releaseRef();
+ static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxCheckboxDisabledOff").releaseRef();
+ static Image* const disabledIndeterminateImage = Image::loadPlatformResource("linuxCheckboxDisabledIndeterminate").releaseRef();
+
+ Image* image;
+
+ if (isIndeterminate(o))
+ image = isEnabled(o) ? indeterminateImage : disabledIndeterminateImage;
+ else if (isChecked(o))
+ image = isEnabled(o) ? checkedImage : disabledCheckedImage;
+ else
+ image = isEnabled(o) ? uncheckedImage : disabledUncheckedImage;
+
+ i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth));
+ return false;
+}
+
+void RenderThemeChromiumSkia::setCheckboxSize(RenderStyle* style) const
+{
+ // If the width and height are both specified, then we have nothing to do.
+ if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
+ return;
+
+ // FIXME: A hard-coded size of 13 is used. This is wrong but necessary
+ // for now. It matches Firefox. At different DPI settings on Windows,
+ // querying the theme gives you a larger size that accounts for the higher
+ // DPI. Until our entire engine honors a DPI setting other than 96, we
+ // can't rely on the theme's metrics.
+ const IntSize size(widgetStandardHeight, widgetStandardWidth);
+ setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumSkia::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ static Image* const checkedImage = Image::loadPlatformResource("linuxRadioOn").releaseRef();
+ static Image* const uncheckedImage = Image::loadPlatformResource("linuxRadioOff").releaseRef();
+ static Image* const disabledCheckedImage = Image::loadPlatformResource("linuxRadioDisabledOn").releaseRef();
+ static Image* const disabledUncheckedImage = Image::loadPlatformResource("linuxRadioDisabledOff").releaseRef();
+
+ Image* image;
+ if (this->isEnabled(o))
+ image = this->isChecked(o) ? checkedImage : uncheckedImage;
+ else
+ image = this->isChecked(o) ? disabledCheckedImage : disabledUncheckedImage;
+
+ i.context->drawImage(image, o->style()->colorSpace(), center(rect, widgetStandardHeight, widgetStandardWidth));
+ return false;
+}
+
+void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
+{
+ // Use same sizing for radio box as checkbox.
+ setCheckboxSize(style);
+}
+
+static SkColor brightenColor(double h, double s, double l, float brightenAmount)
+{
+ l += brightenAmount;
+ if (l > 1.0)
+ l = 1.0;
+ if (l < 0.0)
+ l = 0.0;
+
+ return makeRGBAFromHSLA(h, s, l, 1.0);
+}
+
+static void paintButtonLike(RenderTheme* theme, RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ SkPaint paint;
+ SkRect skrect;
+ const int right = rect.x() + rect.width();
+ const int bottom = rect.y() + rect.height();
+ SkColor baseColor = SkColorSetARGB(0xff, 0xdd, 0xdd, 0xdd);
+ if (o->hasBackground())
+ baseColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
+ double h, s, l;
+ Color(baseColor).getHSL(h, s, l);
+ // Our standard gradient is from 0xdd to 0xf8. This is the amount of
+ // increased luminance between those values.
+ SkColor lightColor(brightenColor(h, s, l, 0.105));
+
+ // If the button is too small, fallback to drawing a single, solid color
+ if (rect.width() < 5 || rect.height() < 5) {
+ paint.setColor(baseColor);
+ skrect.set(rect.x(), rect.y(), right, bottom);
+ canvas->drawRect(skrect, paint);
+ return;
+ }
+
+ const int borderAlpha = theme->isHovered(o) ? 0x80 : 0x55;
+ paint.setARGB(borderAlpha, 0, 0, 0);
+ canvas->drawLine(rect.x() + 1, rect.y(), right - 1, rect.y(), paint);
+ canvas->drawLine(right - 1, rect.y() + 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x() + 1, bottom - 1, right - 1, bottom - 1, paint);
+ canvas->drawLine(rect.x(), rect.y() + 1, rect.x(), bottom - 1, paint);
+
+ paint.setColor(SK_ColorBLACK);
+ SkPoint p[2];
+ const int lightEnd = theme->isPressed(o) ? 1 : 0;
+ const int darkEnd = !lightEnd;
+ p[lightEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y()));
+ p[darkEnd].set(SkIntToScalar(rect.x()), SkIntToScalar(bottom - 1));
+ SkColor colors[2];
+ colors[0] = lightColor;
+ colors[1] = baseColor;
+
+ SkShader* shader = SkGradientShader::CreateLinear(
+ p, colors, NULL, 2, SkShader::kClamp_TileMode, NULL);
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setShader(shader);
+ shader->unref();
+
+ skrect.set(rect.x() + 1, rect.y() + 1, right - 1, bottom - 1);
+ canvas->drawRect(skrect, paint);
+
+ paint.setShader(NULL);
+ paint.setColor(brightenColor(h, s, l, -0.0588));
+ canvas->drawPoint(rect.x() + 1, rect.y() + 1, paint);
+ canvas->drawPoint(right - 2, rect.y() + 1, paint);
+ canvas->drawPoint(rect.x() + 1, bottom - 2, paint);
+ canvas->drawPoint(right - 2, bottom - 2, paint);
+}
+
+bool RenderThemeChromiumSkia::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ paintButtonLike(this, o, i, rect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ if (style->appearance() == PushButtonPart) {
+ // Ignore line-height.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+ }
+}
+
+
+bool RenderThemeChromiumSkia::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ return true;
+}
+
+bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Ignore line-height.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+ return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
+ style->setWidth(Length(cancelButtonSize, Fixed));
+ style->setHeight(Length(cancelButtonSize, Fixed));
+}
+
+IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, IntRect partRect, const IntRect& localOffset) const
+{
+ // Compute an offset between the part renderer and the input renderer.
+ IntSize offsetFromInputRenderer = -(partRenderer->offsetFromAncestorContainer(inputRenderer));
+ // Move the rect into partRenderer's coords.
+ partRect.move(offsetFromInputRenderer);
+ // Account for the local drawing offset.
+ partRect.move(localOffset.x(), localOffset.y());
+
+ return partRect;
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+ // Get the renderer of <input> element.
+ Node* input = cancelButtonObject->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+ RenderBox* inputRenderBox = toRenderBox(input->renderer());
+ IntRect inputContentBox = inputRenderBox->contentBoxRect();
+
+ // Make sure the scaled button stays square and will fit in its parent's box.
+ int cancelButtonSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height()));
+ // Calculate cancel button's coordinates relative to the input element.
+ // Center the button vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ IntRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
+ inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
+ cancelButtonSize, cancelButtonSize);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
+
+ static Image* cancelImage = Image::loadPlatformResource("searchCancel").releaseRef();
+ static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").releaseRef();
+ paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage,
+ cancelButtonObject->style()->colorSpace(), paintingRect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ IntSize emptySize(1, 11);
+ style->setWidth(Length(emptySize.width(), Fixed));
+ style->setHeight(Length(emptySize.height(), Fixed));
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the decoration size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ style->setWidth(Length(magnifierSize, Fixed));
+ style->setHeight(Length(magnifierSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+ // Get the renderer of <input> element.
+ Node* input = magnifierObject->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+ RenderBox* inputRenderBox = toRenderBox(input->renderer());
+ IntRect inputContentBox = inputRenderBox->contentBoxRect();
+
+ // Make sure the scaled decoration stays square and will fit in its parent's box.
+ int magnifierSize = std::min(inputContentBox.width(), std::min(inputContentBox.height(), r.height()));
+ // Calculate decoration's coordinates relative to the input element.
+ // Center the decoration vertically. Round up though, so if it has to be one pixel off-center, it will
+ // be one pixel closer to the bottom of the field. This tends to look better with the text.
+ IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
+ inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2,
+ magnifierSize, magnifierSize);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").releaseRef();
+ paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
+{
+ // Scale the button size based on the font size
+ float fontScale = style->fontSize() / defaultControlFontPixelSize;
+ int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+ maxSearchFieldResultsDecorationSize));
+ int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+ style->setWidth(Length(magnifierWidth, Fixed));
+ style->setHeight(Length(magnifierHeight, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+ // Get the renderer of <input> element.
+ Node* input = magnifierObject->node()->shadowAncestorNode();
+ if (!input->renderer()->isBox())
+ return false;
+ RenderBox* inputRenderBox = toRenderBox(input->renderer());
+ IntRect inputContentBox = inputRenderBox->contentBoxRect();
+
+ // Make sure the scaled decoration will fit in its parent's box.
+ int magnifierHeight = std::min(inputContentBox.height(), r.height());
+ int magnifierWidth = std::min(inputContentBox.width(), static_cast<int>(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize));
+ IntRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
+ inputContentBox.y() + (inputContentBox.height() - magnifierHeight + 1) / 2,
+ magnifierWidth, magnifierHeight);
+ IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+
+ static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").releaseRef();
+ paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintMediaControlsBackground(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaTimelineContainer, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderObject* object) const
+{
+#if ENABLE(VIDEO)
+ RenderMediaControlsChromium::adjustMediaSliderThumbSize(object);
+#else
+ UNUSED_PARAM(object);
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+#if ENABLE(VIDEO)
+ return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
+#else
+ UNUSED_PARAM(object);
+ UNUSED_PARAM(paintInfo);
+ UNUSED_PARAM(rect);
+ return false;
+#endif
+}
+
+void RenderThemeChromiumSkia::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const
+{
+ // Height is locked to auto on all browsers.
+ style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumSkia::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ const int right = rect.x() + rect.width();
+ const int middle = rect.y() + rect.height() / 2;
+
+ paintButtonLike(this, o, i, rect);
+
+ SkPaint paint;
+ paint.setColor(SK_ColorBLACK);
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ int arrowXPosition = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
+ SkPath path;
+ path.moveTo(arrowXPosition, middle - 3);
+ path.rLineTo(6, 0);
+ path.rLineTo(-3, 6);
+ path.close();
+ canvas->drawPath(path, paint);
+
+ return false;
+}
+
+void RenderThemeChromiumSkia::adjustMenuListButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ adjustMenuListStyle(selector, style, e);
+}
+
+// Used to paint styled menulists (i.e. with a non-default border)
+bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ return paintMenuList(o, i, rect);
+}
+
+bool RenderThemeChromiumSkia::paintSliderTrack(RenderObject*, const PaintInfo& i, const IntRect& rect)
+{
+ // Just paint a grey box for now (matches the color of a scrollbar background.
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+ int verticalCenter = rect.y() + rect.height() / 2;
+ int top = std::max(rect.y(), verticalCenter - 2);
+ int bottom = std::min(rect.y() + rect.height(), verticalCenter + 2);
+
+ SkPaint paint;
+ const SkColor grey = SkColorSetARGB(0xff, 0xe3, 0xdd, 0xd8);
+ paint.setColor(grey);
+
+ SkRect skrect;
+ skrect.set(rect.x(), top, rect.x() + rect.width(), bottom);
+ canvas->drawRect(skrect, paint);
+
+ return false;
+}
+
+bool RenderThemeChromiumSkia::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+ // Make a thumb similar to the scrollbar thumb.
+ const bool hovered = isHovered(o) || toRenderSlider(o->parent())->inDragMode();
+ const int midx = rect.x() + rect.width() / 2;
+ const int midy = rect.y() + rect.height() / 2;
+ const bool vertical = (o->style()->appearance() == SliderThumbVerticalPart);
+ SkCanvas* const canvas = i.context->platformContext()->canvas();
+
+ const SkColor thumbLightGrey = SkColorSetARGB(0xff, 0xf4, 0xf2, 0xef);
+ const SkColor thumbDarkGrey = SkColorSetARGB(0xff, 0xea, 0xe5, 0xe0);
+ SkPaint paint;
+ paint.setColor(hovered ? SK_ColorWHITE : thumbLightGrey);
+
+ SkIRect skrect;
+ if (vertical)
+ skrect.set(rect.x(), rect.y(), midx + 1, rect.bottom());
+ else
+ skrect.set(rect.x(), rect.y(), rect.right(), midy + 1);
+
+ canvas->drawIRect(skrect, paint);
+
+ paint.setColor(hovered ? thumbLightGrey : thumbDarkGrey);
+
+ if (vertical)
+ skrect.set(midx + 1, rect.y(), rect.right(), rect.bottom());
+ else
+ skrect.set(rect.x(), midy + 1, rect.right(), rect.bottom());
+
+ canvas->drawIRect(skrect, paint);
+
+ const SkColor borderDarkGrey = SkColorSetARGB(0xff, 0x9d, 0x96, 0x8e);
+ paint.setColor(borderDarkGrey);
+ drawBox(canvas, rect, paint);
+
+ if (rect.height() > 10 && rect.width() > 10) {
+ drawHorizLine(canvas, midx - 2, midx + 2, midy, paint);
+ drawHorizLine(canvas, midx - 2, midx + 2, midy - 3, paint);
+ drawHorizLine(canvas, midx - 2, midx + 2, midy + 3, paint);
+ }
+
+ return false;
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
+{
+ return menuListInternalPadding(style, BottomPadding);
+}
+
+#if ENABLE(VIDEO)
+bool RenderThemeChromiumSkia::shouldRenderMediaControlPart(ControlPart part, Element* e)
+{
+ return RenderMediaControlsChromium::shouldRenderMediaControlPart(part, e);
+}
+#endif
+
+// static
+void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
+{
+ defaultFontSize = static_cast<float>(fontSize);
+}
+
+double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
+{
+ return RenderTheme::caretBlinkInterval();
+}
+
+int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
+{
+ // This internal padding is in addition to the user-supplied padding.
+ // Matches the FF behavior.
+ int padding = styledMenuListInternalPadding[paddingType];
+
+ // Reserve the space for right arrow here. The rest of the padding is
+ // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
+ // RenderMenuList to lay out the individual items in the popup.
+ // If the MenuList actually has appearance "NoAppearance", then that means
+ // we don't draw a button, so don't reserve space for it.
+ const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
+ if (paddingType == barType && style->appearance() != NoControlPart)
+ padding += ScrollbarTheme::nativeTheme()->scrollbarThickness();
+
+ return padding;
+}
+
+#if ENABLE(PROGRESS_TAG)
+
+//
+// Following values are come from default of GTK+
+//
+static const int progressDeltaPixelsPerSecond = 100;
+static const int progressActivityBlocks = 5;
+static const int progressAnimationFrmaes = 10;
+static const double progressAnimationInterval = 0.125;
+
+IntRect RenderThemeChromiumSkia::determinateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+ int dx = rect.width() * renderProgress->position();
+ if (renderProgress->style()->direction() == RTL)
+ return IntRect(rect.x() + rect.width() - dx, rect.y(), dx, rect.height());
+ return IntRect(rect.x(), rect.y(), dx, rect.height());
+}
+
+IntRect RenderThemeChromiumSkia::indeterminateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+
+ int valueWidth = rect.width() / progressActivityBlocks;
+ int movableWidth = rect.width() - valueWidth;
+ if (movableWidth <= 0)
+ return IntRect();
+
+ double progress = renderProgress->animationProgress();
+ if (progress < 0.5)
+ return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWidth, rect.height());
+ return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), valueWidth, rect.height());
+}
+
+double RenderThemeChromiumSkia::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+ return progressAnimationInterval;
+}
+
+double RenderThemeChromiumSkia::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+ return progressAnimationInterval * progressAnimationFrmaes * 2; // "2" for back and forth
+}
+
+bool RenderThemeChromiumSkia::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+ static Image* barImage = Image::loadPlatformResource("linuxProgressBar").releaseRef();
+ static Image* valueImage = Image::loadPlatformResource("linuxProgressValue").releaseRef();
+ static Image* leftBorderImage = Image::loadPlatformResource("linuxProgressBorderLeft").releaseRef();
+ static Image* rightBorderImage = Image::loadPlatformResource("linuxProgressBorderRight").releaseRef();
+ ASSERT(barImage->height() == valueImage->height());
+
+ if (!renderObject->isProgress())
+ return true;
+
+ paintInfo.context->platformContext()->setImageResamplingHint(barImage->size(), rect.size());
+
+ RenderProgress* renderProgress = toRenderProgress(renderObject);
+ double tileScale = static_cast<double>(rect.height()) / barImage->height();
+ IntSize barTileSize(static_cast<int>(barImage->width() * tileScale), rect.height());
+ ColorSpace colorSpace = renderObject->style()->colorSpace();
+
+ paintInfo.context->drawTiledImage(barImage, colorSpace, rect, IntPoint(0, 0), barTileSize);
+
+ IntRect valueRect = progressValueRectFor(renderProgress, rect);
+ if (valueRect.width()) {
+
+ IntSize valueTileSize(std::max(1, static_cast<int>(valueImage->width() * tileScale)), valueRect.height());
+
+ int leftOffset = valueRect.x() - rect.x();
+ int roundedLeftOffset= (leftOffset / valueTileSize.width()) * valueTileSize.width();
+ int dstLeftValueWidth = roundedLeftOffset - leftOffset + (leftOffset % valueImage->width()) ? valueTileSize.width() : 0;
+
+ IntRect dstLeftValueRect(valueRect.x(), valueRect.y(), dstLeftValueWidth, valueRect.height());
+ int srcLeftValueWidth = dstLeftValueWidth / tileScale;
+ IntRect srcLeftValueRect(valueImage->width() - srcLeftValueWidth, 0, srcLeftValueWidth, valueImage->height());
+ paintInfo.context->drawImage(valueImage, colorSpace, dstLeftValueRect, srcLeftValueRect);
+
+ int rightOffset = valueRect.right() - rect.x();
+ int roundedRightOffset = (rightOffset / valueTileSize.width()) * valueTileSize.width();
+ int dstRightValueWidth = rightOffset - roundedRightOffset;
+ IntRect dstRightValueRect(rect.x() + roundedRightOffset, valueRect.y(), dstRightValueWidth, valueTileSize.height());
+ int srcRightValueWidth = dstRightValueWidth / tileScale;
+ IntRect srcRightValueRect(0, 0, srcRightValueWidth, valueImage->height());
+ paintInfo.context->drawImage(valueImage, colorSpace, dstRightValueRect, srcRightValueRect);
+
+ IntRect alignedValueRect(dstLeftValueRect.right(), dstLeftValueRect.y(),
+ dstRightValueRect.x() - dstLeftValueRect.right(), dstLeftValueRect.height());
+ paintInfo.context->drawTiledImage(valueImage, colorSpace, alignedValueRect, IntPoint(0, 0), valueTileSize);
+ }
+
+ int dstLeftBorderWidth = leftBorderImage->width() * tileScale;
+ IntRect dstLeftBorderRect(rect.x(), rect.y(), dstLeftBorderWidth, rect.height());
+ paintInfo.context->drawImage(leftBorderImage, colorSpace, dstLeftBorderRect, leftBorderImage->rect());
+
+ int dstRightBorderWidth = rightBorderImage->width() * tileScale;
+ IntRect dstRightBorderRect(rect.right() - dstRightBorderWidth, rect.y(), dstRightBorderWidth, rect.height());
+ paintInfo.context->drawImage(rightBorderImage, colorSpace, dstRightBorderRect, rightBorderImage->rect());
+
+ paintInfo.context->platformContext()->clearImageResamplingHint();
+
+ return false;
+}
+
+
+IntRect RenderThemeChromiumSkia::progressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+ return renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, rect) : indeterminateProgressValueRectFor(renderProgress, rect);
+}
+
+#endif
+
+} // namespace WebCore