diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/rendering/RenderThemeChromiumWin.cpp | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/rendering/RenderThemeChromiumWin.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderThemeChromiumWin.cpp | 770 |
1 files changed, 770 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/RenderThemeChromiumWin.cpp b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp new file mode 100644 index 0000000..be670ff --- /dev/null +++ b/Source/WebCore/rendering/RenderThemeChromiumWin.cpp @@ -0,0 +1,770 @@ +/* + * This file is part of the WebKit project. + * + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2008, 2009 Google, Inc. + * Copyright (C) 2009 Kenneth Rohde Christiansen + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include "RenderThemeChromiumWin.h" + +#include <windows.h> +#include <uxtheme.h> +#include <vssym32.h> + +#include "CSSValueKeywords.h" +#include "ChromiumBridge.h" +#include "CurrentTime.h" +#include "FontSelector.h" +#include "FontUtilsChromiumWin.h" +#include "GraphicsContext.h" +#include "HTMLMediaElement.h" +#include "HTMLNames.h" +#include "MediaControlElements.h" +#include "RenderBox.h" +#include "RenderProgress.h" +#include "RenderSlider.h" +#include "ScrollbarTheme.h" +#include "TransparencyWin.h" +#include "WindowsVersion.h" + +// FIXME: This dependency should eventually be removed. +#include <skia/ext/skia_utils_win.h> + +#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \ + offsetof(structName, member) + \ + (sizeof static_cast<structName*>(0)->member) +#define NONCLIENTMETRICS_SIZE_PRE_VISTA \ + SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont) + +namespace WebCore { + +// The standard width for the menu list drop-down button when run under +// layout test mode. Use the value that's currently captured in most baselines. +static const int kStandardMenuListButtonWidth = 17; + +namespace { +class ThemePainter { +public: + ThemePainter(GraphicsContext* context, const IntRect& r) + { + TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM()); + m_helper.init(context, getLayerMode(context, transformMode), transformMode, r); + + if (!m_helper.context()) { + // TransparencyWin doesn't have well-defined copy-ctor nor op=() + // so we re-initialize it instead of assigning a fresh istance. + // On the reinitialization, we fallback to use NoLayer mode. + // Note that the original initialization failure can be caused by + // a failure of an internal buffer allocation and NoLayer mode + // does not have such buffer allocations. + m_helper.~TransparencyWin(); + new (&m_helper) TransparencyWin(); + m_helper.init(context, TransparencyWin::NoLayer, transformMode, r); + } + } + + ~ThemePainter() + { + m_helper.composite(); + } + + GraphicsContext* context() { return m_helper.context(); } + const IntRect& drawRect() { return m_helper.drawRect(); } + +private: + + static bool canvasHasMultipleLayers(const SkCanvas* canvas) + { + SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false); + iter.next(); // There is always at least one layer. + return !iter.done(); // There is > 1 layer if the the iterator can stil advance. + } + + static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode) + { + if (context->platformContext()->isDrawingToImageBuffer()) // Might have transparent background. + return TransparencyWin::WhiteLayer; + if (canvasHasMultipleLayers(context->platformContext()->canvas())) // Needs antialiasing help. + return TransparencyWin::OpaqueCompositeLayer; + // Nothing interesting. + return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer; + } + + static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix) + { + if (matrix.b() || matrix.c()) // Skew. + return TransparencyWin::Untransform; + if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale. + return TransparencyWin::ScaleTransform; + // Nothing interesting. + return TransparencyWin::KeepTransform; + } + + TransparencyWin m_helper; +}; + +} // namespace + +static void getNonClientMetrics(NONCLIENTMETRICS* metrics) +{ + static UINT size = isVistaOrNewer() ? + sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA; + metrics->cbSize = size; + bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0); + ASSERT(success); +} + +static FontDescription smallSystemFont; +static FontDescription menuFont; +static FontDescription labelFont; + +// Internal static helper functions. We don't put them in an anonymous +// namespace so they have easier access to the WebCore namespace. + +static bool supportsFocus(ControlPart appearance) +{ + switch (appearance) { + case PushButtonPart: + case ButtonPart: + case DefaultButtonPart: + case SearchFieldPart: + case TextFieldPart: + case TextAreaPart: + return true; + } + return false; +} + +// Return the height of system font |font| in pixels. We use this size by +// default for some non-form-control elements. +static float systemFontSize(const LOGFONT& font) +{ + float size = -font.lfHeight; + if (size < 0) { + HFONT hFont = CreateFontIndirect(&font); + if (hFont) { + HDC hdc = GetDC(0); // What about printing? Is this the right DC? + if (hdc) { + HGDIOBJ hObject = SelectObject(hdc, hFont); + TEXTMETRIC tm; + GetTextMetrics(hdc, &tm); + SelectObject(hdc, hObject); + ReleaseDC(0, hdc); + size = tm.tmAscent; + } + DeleteObject(hFont); + } + } + + // The "codepage 936" bit here is from Gecko; apparently this helps make + // fonts more legible in Simplified Chinese where the default font size is + // too small. + // + // FIXME: http://b/1119883 Since this is only used for "small caption", + // "menu", and "status bar" objects, I'm not sure how much this even + // matters. Plus the Gecko patch went in back in 2002, and maybe this + // isn't even relevant anymore. We should investigate whether this should + // be removed, or perhaps broadened to be "any CJK locale". + // + return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size; +} + +// Converts |points| to pixels. One point is 1/72 of an inch. +static float pointsToPixels(float points) +{ + static float pixelsPerInch = 0.0f; + if (!pixelsPerInch) { + HDC hdc = GetDC(0); // What about printing? Is this the right DC? + if (hdc) { // Can this ever actually be NULL? + pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(0, hdc); + } else { + pixelsPerInch = 96.0f; + } + } + + static const float pointsPerInch = 72.0f; + return points / pointsPerInch * pixelsPerInch; +} + +static double querySystemBlinkInterval(double defaultInterval) +{ + UINT blinkTime = GetCaretBlinkTime(); + if (!blinkTime) + return defaultInterval; + if (blinkTime == INFINITE) + return 0; + return blinkTime / 1000.0; +} + +PassRefPtr<RenderTheme> RenderThemeChromiumWin::create() +{ + return adoptRef(new RenderThemeChromiumWin); +} + +PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) +{ + static RenderTheme* rt = RenderThemeChromiumWin::create().releaseRef(); + return rt; +} + +bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const +{ + // Let webkit draw one of its halo rings around any focused element, + // except push buttons. For buttons we use the windows PBS_DEFAULTED + // styling to give it a blue border. + return style->appearance() == ButtonPart + || style->appearance() == PushButtonPart; +} + +Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const +{ + if (ChromiumBridge::layoutTestMode()) + return Color(0x00, 0x00, 0xff); // Royal blue. + COLORREF color = GetSysColor(COLOR_HIGHLIGHT); + return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); +} + +Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const +{ + if (ChromiumBridge::layoutTestMode()) + return Color(0x99, 0x99, 0x99); // Medium gray. + COLORREF color = GetSysColor(COLOR_GRAYTEXT); + return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); +} + +Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const +{ + if (ChromiumBridge::layoutTestMode()) + return Color(0xff, 0xff, 0xcc); // Pale yellow. + COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT); + return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff); +} + +Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const +{ + return Color::white; +} + +Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const +{ + return Color(0xff, 0x96, 0x32); // Orange. +} + +Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const +{ + return Color(0xff, 0xff, 0x96); // Yellow. +} + +void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const +{ + // This logic owes much to RenderThemeSafari.cpp. + FontDescription* cachedDesc = 0; + AtomicString faceName; + float fontSize = 0; + switch (propId) { + case CSSValueSmallCaption: + cachedDesc = &smallSystemFont; + if (!smallSystemFont.isAbsoluteSize()) { + NONCLIENTMETRICS metrics; + getNonClientMetrics(&metrics); + faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName)); + fontSize = systemFontSize(metrics.lfSmCaptionFont); + } + break; + case CSSValueMenu: + cachedDesc = &menuFont; + if (!menuFont.isAbsoluteSize()) { + NONCLIENTMETRICS metrics; + getNonClientMetrics(&metrics); + faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName)); + fontSize = systemFontSize(metrics.lfMenuFont); + } + break; + case CSSValueStatusBar: + cachedDesc = &labelFont; + if (!labelFont.isAbsoluteSize()) { + NONCLIENTMETRICS metrics; + getNonClientMetrics(&metrics); + faceName = metrics.lfStatusFont.lfFaceName; + fontSize = systemFontSize(metrics.lfStatusFont); + } + break; + case CSSValueWebkitMiniControl: + case CSSValueWebkitSmallControl: + case CSSValueWebkitControl: + faceName = defaultGUIFont(); + // Why 2 points smaller? Because that's what Gecko does. + fontSize = defaultFontSize - pointsToPixels(2); + break; + default: + faceName = defaultGUIFont(); + fontSize = defaultFontSize; + break; + } + + if (!cachedDesc) + cachedDesc = &fontDescription; + + if (fontSize) { + cachedDesc->firstFamily().setFamily(faceName); + cachedDesc->setIsAbsoluteSize(true); + cachedDesc->setGenericFamily(FontDescription::NoFamily); + cachedDesc->setSpecifiedSize(fontSize); + cachedDesc->setWeight(FontWeightNormal); + cachedDesc->setItalic(false); + } + fontDescription = *cachedDesc; +} + +// Map a CSSValue* system color to an index understood by GetSysColor(). +static int cssValueIdToSysColorIndex(int cssValueId) +{ + switch (cssValueId) { + case CSSValueActiveborder: return COLOR_ACTIVEBORDER; + case CSSValueActivecaption: return COLOR_ACTIVECAPTION; + case CSSValueAppworkspace: return COLOR_APPWORKSPACE; + case CSSValueBackground: return COLOR_BACKGROUND; + case CSSValueButtonface: return COLOR_BTNFACE; + case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT; + case CSSValueButtonshadow: return COLOR_BTNSHADOW; + case CSSValueButtontext: return COLOR_BTNTEXT; + case CSSValueCaptiontext: return COLOR_CAPTIONTEXT; + case CSSValueGraytext: return COLOR_GRAYTEXT; + case CSSValueHighlight: return COLOR_HIGHLIGHT; + case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT; + case CSSValueInactiveborder: return COLOR_INACTIVEBORDER; + case CSSValueInactivecaption: return COLOR_INACTIVECAPTION; + case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT; + case CSSValueInfobackground: return COLOR_INFOBK; + case CSSValueInfotext: return COLOR_INFOTEXT; + case CSSValueMenu: return COLOR_MENU; + case CSSValueMenutext: return COLOR_MENUTEXT; + case CSSValueScrollbar: return COLOR_SCROLLBAR; + case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW; + case CSSValueThreedface: return COLOR_3DFACE; + case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT; + case CSSValueThreedlightshadow: return COLOR_3DLIGHT; + case CSSValueThreedshadow: return COLOR_3DSHADOW; + case CSSValueWindow: return COLOR_WINDOW; + case CSSValueWindowframe: return COLOR_WINDOWFRAME; + case CSSValueWindowtext: return COLOR_WINDOWTEXT; + default: return -1; // Unsupported CSSValue + } +} + +Color RenderThemeChromiumWin::systemColor(int cssValueId) const +{ + int sysColorIndex = cssValueIdToSysColorIndex(cssValueId); + if (ChromiumBridge::layoutTestMode() || (sysColorIndex == -1)) + return RenderTheme::systemColor(cssValueId); + + COLORREF color = GetSysColor(sysColorIndex); + return Color(GetRValue(color), GetGValue(color), GetBValue(color)); +} + +void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const +{ + // These sizes match what WinXP draws for various menus. + const int sliderThumbAlongAxis = 11; + const int sliderThumbAcrossAxis = 21; + if (o->style()->appearance() == SliderThumbHorizontalPart) { + o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed)); + o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed)); + } else if (o->style()->appearance() == SliderThumbVerticalPart) { + o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed)); + o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed)); + } else + RenderThemeChromiumSkia::adjustSliderThumbSize(o); +} + +bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + return paintButton(o, i, r); +} +bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + return paintButton(o, i, r); +} + +bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + const ThemeData& themeData = getThemeData(o); + + ThemePainter painter(i.context, r); + ChromiumBridge::paintButton(painter.context(), + themeData.m_part, + themeData.m_state, + themeData.m_classicState, + painter.drawRect()); + return false; +} + +bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + return paintTextFieldInternal(o, i, r, true); +} + +bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + const ThemeData& themeData = getThemeData(o); + + ThemePainter painter(i.context, r); + ChromiumBridge::paintTrackbar(painter.context(), + themeData.m_part, + themeData.m_state, + themeData.m_classicState, + painter.drawRect()); + return false; +} + +bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + return paintSliderTrack(o, i, r); +} + +static int menuListButtonWidth() +{ + static int width = ChromiumBridge::layoutTestMode() ? kStandardMenuListButtonWidth : GetSystemMetrics(SM_CXVSCROLL); + return width; +} + +// Used to paint unstyled menulists (i.e. with the default border) +bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + if (!o->isBox()) + return false; + + const RenderBox* box = toRenderBox(o); + int borderRight = box->borderRight(); + int borderLeft = box->borderLeft(); + int borderTop = box->borderTop(); + int borderBottom = box->borderBottom(); + + // If all the borders are 0, then tell skia not to paint the border on the + // textfield. FIXME: http://b/1210017 Figure out how to get Windows to not + // draw individual borders and then pass that to skia so we can avoid + // drawing any borders that are set to 0. For non-zero borders, we draw the + // border, but webkit just draws over it. + bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom); + + paintTextFieldInternal(o, i, r, drawEdges); + + // Take padding and border into account. If the MenuList is smaller than + // the size of a button, make sure to shrink it appropriately and not put + // its x position to the left of the menulist. + const int buttonWidth = menuListButtonWidth(); + int spacingLeft = borderLeft + box->paddingLeft(); + int spacingRight = borderRight + box->paddingRight(); + int spacingTop = borderTop + box->paddingTop(); + int spacingBottom = borderBottom + box->paddingBottom(); + + int buttonX; + if (r.right() - r.x() < buttonWidth) + buttonX = r.x(); + else + buttonX = o->style()->direction() == LTR ? r.right() - spacingRight - buttonWidth : r.x() + spacingLeft; + + // Compute the rectangle of the button in the destination image. + IntRect rect(buttonX, + r.y() + spacingTop, + std::min(buttonWidth, r.right() - r.x()), + r.height() - (spacingTop + spacingBottom)); + + // Get the correct theme data for a textfield and paint the menu. + ThemePainter painter(i.context, rect); + ChromiumBridge::paintMenuList(painter.context(), + CP_DROPDOWNBUTTON, + determineState(o), + determineClassicState(o), + painter.drawRect()); + return false; +} + +// static +void RenderThemeChromiumWin::setDefaultFontSize(int fontSize) +{ + RenderThemeChromiumSkia::setDefaultFontSize(fontSize); + + // Reset cached fonts. + smallSystemFont = menuFont = labelFont = FontDescription(); +} + +double RenderThemeChromiumWin::caretBlinkIntervalInternal() const +{ + // This involves a system call, so we cache the result. + static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval()); + return blinkInterval; +} + +unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart) +{ + unsigned result = TS_NORMAL; + ControlPart appearance = o->style()->appearance(); + if (!isEnabled(o)) + result = TS_DISABLED; + else if (isReadOnlyControl(o)) + result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED; + // Active overrides hover and focused. + else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) + result = TS_PRESSED; + else if (supportsFocus(appearance) && isFocused(o)) + result = ETS_FOCUSED; + else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) + result = TS_HOT; + + // CBS_UNCHECKED*: 1-4 + // CBS_CHECKED*: 5-8 + // CBS_MIXED*: 9-12 + if (isIndeterminate(o)) + result += 8; + else if (isChecked(o)) + result += 4; + return result; +} + +unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o) +{ + unsigned result = TUS_NORMAL; + if (!isEnabled(o->parent())) + result = TUS_DISABLED; + else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent())) + result = TUS_FOCUSED; + else if (toRenderSlider(o->parent())->inDragMode()) + result = TUS_PRESSED; + else if (isHovered(o)) + result = TUS_HOT; + return result; +} + +unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart) +{ + unsigned result = 0; + + ControlPart part = o->style()->appearance(); + + // Sliders are always in the normal state. + if (part == SliderHorizontalPart || part == SliderVerticalPart) + return result; + + // So are readonly text fields. + if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart)) + return result; + + if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { + if (!isEnabled(o->parent())) + result = DFCS_INACTIVE; + else if (toRenderSlider(o->parent())->inDragMode()) // Active supersedes hover + result = DFCS_PUSHED; + else if (isHovered(o)) + result = DFCS_HOT; + } else { + if (!isEnabled(o) || isReadOnlyControl(o)) + result = DFCS_INACTIVE; + // Active supersedes hover + else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o)) + result = DFCS_PUSHED; + else if (supportsFocus(part) && isFocused(o)) // So does focused + result = 0; + else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o)) + result = DFCS_HOT; + // Classic theme can't represent indeterminate states. Use unchecked appearance. + if (isChecked(o) && !isIndeterminate(o)) + result |= DFCS_CHECKED; + } + return result; +} + +ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart) +{ + ThemeData result; + switch (o->style()->appearance()) { + case CheckboxPart: + result.m_part = BP_CHECKBOX; + result.m_state = determineState(o); + result.m_classicState = DFCS_BUTTONCHECK; + break; + case RadioPart: + result.m_part = BP_RADIOBUTTON; + result.m_state = determineState(o); + result.m_classicState = DFCS_BUTTONRADIO; + break; + case PushButtonPart: + case ButtonPart: + result.m_part = BP_PUSHBUTTON; + result.m_state = determineState(o); + result.m_classicState = DFCS_BUTTONPUSH; + break; + case SliderHorizontalPart: + result.m_part = TKP_TRACK; + result.m_state = TRS_NORMAL; + break; + case SliderVerticalPart: + result.m_part = TKP_TRACKVERT; + result.m_state = TRVS_NORMAL; + break; + case SliderThumbHorizontalPart: + result.m_part = TKP_THUMBBOTTOM; + result.m_state = determineSliderThumbState(o); + break; + case SliderThumbVerticalPart: + result.m_part = TKP_THUMBVERT; + result.m_state = determineSliderThumbState(o); + break; + case ListboxPart: + case MenulistPart: + case MenulistButtonPart: + case SearchFieldPart: + case TextFieldPart: + case TextAreaPart: + result.m_part = EP_EDITTEXT; + result.m_state = determineState(o); + break; + case InnerSpinButtonPart: + result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN; + result.m_state = determineState(o, subPart); + result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN; + break; + } + + result.m_classicState |= determineClassicState(o, subPart); + + return result; +} + +bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o, + const PaintInfo& i, + const IntRect& r, + bool drawEdges) +{ + // Fallback to white if the specified color object is invalid. + // (Note ChromiumBridge::paintTextField duplicates this check). + Color backgroundColor(Color::white); + if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid()) + backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor); + + // If we have background-image, don't fill the content area to expose the + // parent's background. Also, we shouldn't fill the content area if the + // alpha of the color is 0. The API of Windows GDI ignores the alpha. + // + // Note that we should paint the content area white if we have neither the + // background color nor background image explicitly specified to keep the + // appearance of select element consistent with other browsers. + bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha(); + + if (o->style()->hasBorderRadius()) { + // If the style has rounded borders, setup the context to clip the + // background (themed or filled) appropriately. + // FIXME: make sure we do the right thing if css background-clip is set. + i.context->save(); + IntSize topLeft, topRight, bottomLeft, bottomRight; + o->style()->getBorderRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight); + i.context->addRoundedRectClip(r, topLeft, topRight, bottomLeft, bottomRight); + } + { + const ThemeData& themeData = getThemeData(o); + ThemePainter painter(i.context, r); + ChromiumBridge::paintTextField(painter.context(), + themeData.m_part, + themeData.m_state, + themeData.m_classicState, + painter.drawRect(), + backgroundColor, + fillContentArea, + drawEdges); + // End of block commits the painter before restoring context. + } + if (o->style()->hasBorderRadius()) + i.context->restore(); + return false; +} + +void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + int width = ScrollbarTheme::nativeTheme()->scrollbarThickness(); + style->setWidth(Length(width, Fixed)); + style->setMinWidth(Length(width, Fixed)); +} + +bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect) +{ + IntRect half = rect; + + half.setHeight(rect.height() / 2); + const ThemeData& upThemeData = getThemeData(object, SpinButtonUp); + ThemePainter upPainter(info.context, half); + ChromiumBridge::paintSpinButton(upPainter.context(), + upThemeData.m_part, + upThemeData.m_state, + upThemeData.m_classicState, + upPainter.drawRect()); + + half.setY(rect.y() + rect.height() / 2); + const ThemeData& downThemeData = getThemeData(object, SpinButtonDown); + ThemePainter downPainter(info.context, half); + ChromiumBridge::paintSpinButton(downPainter.context(), + downThemeData.m_part, + downThemeData.m_state, + downThemeData.m_classicState, + downPainter.drawRect()); + return false; +} + +#if ENABLE(PROGRESS_TAG) + +// MSDN says that update intervals for the bar is 30ms. +// http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx +static const double progressAnimationFrameRate = 0.033; + +double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const +{ + return progressAnimationFrameRate; +} + +double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const +{ + // On Chromium Windows port, animationProgress() and associated values aren't used. + // So here we can return arbitrary positive value. + return progressAnimationFrameRate; +} + +void RenderThemeChromiumWin::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const +{ +} + +bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + if (!o->isProgress()) + return true; + + RenderProgress* renderProgress = toRenderProgress(o); + // For indeterminate bar, valueRect is ignored and it is computed by the theme engine + // because the animation is a platform detail and WebKit doesn't need to know how. + IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0); + double animatedSeconds = renderProgress->animationStartTime() ? WTF::currentTime() - renderProgress->animationStartTime() : 0; + ThemePainter painter(i.context, r); + ChromiumBridge::paintProgressBar(painter.context(), r, valueRect, renderProgress->isDeterminate(), animatedSeconds); + return false; +} + +#endif + +} // namespace WebCore |