Home | History | Annotate | Download | only in rendering
      1 /*
      2  * This file is part of the WebKit project.
      3  *
      4  * Copyright (C) 2006 Apple Computer, Inc.
      5  * Copyright (C) 2008, 2009 Google, Inc.
      6  * Copyright (C) 2009 Kenneth Rohde Christiansen
      7  *
      8  * This library is free software; you can redistribute it and/or
      9  * modify it under the terms of the GNU Library General Public
     10  * License as published by the Free Software Foundation; either
     11  * version 2 of the License, or (at your option) any later version.
     12  *
     13  * This library is distributed in the hope that it will be useful,
     14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     16  * Library General Public License for more details.
     17  *
     18  * You should have received a copy of the GNU Library General Public License
     19  * along with this library; see the file COPYING.LIB.  If not, write to
     20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     21  * Boston, MA 02111-1307, USA.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "RenderThemeChromiumWin.h"
     27 
     28 #include <windows.h>
     29 #include <uxtheme.h>
     30 #include <vssym32.h>
     31 
     32 #include "ChromiumBridge.h"
     33 #include "CSSValueKeywords.h"
     34 #include "FontSelector.h"
     35 #include "FontUtilsChromiumWin.h"
     36 #include "GraphicsContext.h"
     37 #include "HTMLMediaElement.h"
     38 #include "HTMLNames.h"
     39 #include "MediaControlElements.h"
     40 #include "RenderBox.h"
     41 #include "RenderSlider.h"
     42 #include "ScrollbarTheme.h"
     43 #include "TransparencyWin.h"
     44 #include "WindowsVersion.h"
     45 
     46 // FIXME: This dependency should eventually be removed.
     47 #include <skia/ext/skia_utils_win.h>
     48 
     49 #define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
     50     offsetof(structName, member) + \
     51     (sizeof static_cast<structName*>(0)->member)
     52 #define NONCLIENTMETRICS_SIZE_PRE_VISTA \
     53     SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
     54 
     55 namespace WebCore {
     56 
     57 namespace {
     58 class ThemePainter : public TransparencyWin {
     59 public:
     60     ThemePainter(GraphicsContext* context, const IntRect& r)
     61     {
     62         TransformMode transformMode = getTransformMode(context->getCTM());
     63         init(context, getLayerMode(context, transformMode), transformMode, r);
     64     }
     65 
     66     ~ThemePainter()
     67     {
     68         composite();
     69     }
     70 
     71 private:
     72     static bool canvasHasMultipleLayers(const SkCanvas* canvas)
     73     {
     74         SkCanvas::LayerIter iter(const_cast<SkCanvas*>(canvas), false);
     75         iter.next();  // There is always at least one layer.
     76         return !iter.done();  // There is > 1 layer if the the iterator can stil advance.
     77     }
     78 
     79     static LayerMode getLayerMode(GraphicsContext* context, TransformMode transformMode)
     80     {
     81         if (context->platformContext()->isDrawingToImageBuffer())  // Might have transparent background.
     82             return WhiteLayer;
     83         else if (canvasHasMultipleLayers(context->platformContext()->canvas()))  // Needs antialiasing help.
     84             return OpaqueCompositeLayer;
     85         else  // Nothing interesting.
     86             return transformMode == KeepTransform ? NoLayer : OpaqueCompositeLayer;
     87     }
     88 
     89     static TransformMode getTransformMode(const AffineTransform& matrix)
     90     {
     91         if (matrix.b() != 0 || matrix.c() != 0)  // Skew.
     92             return Untransform;
     93         else if (matrix.a() != 1.0 || matrix.d() != 1.0)  // Scale.
     94             return ScaleTransform;
     95         else  // Nothing interesting.
     96             return KeepTransform;
     97     }
     98 };
     99 
    100 }  // namespace
    101 
    102 static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
    103 {
    104     static UINT size = WebCore::isVistaOrNewer() ?
    105         sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
    106     metrics->cbSize = size;
    107     bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
    108     ASSERT(success);
    109 }
    110 
    111 static FontDescription smallSystemFont;
    112 static FontDescription menuFont;
    113 static FontDescription labelFont;
    114 
    115 // Internal static helper functions.  We don't put them in an anonymous
    116 // namespace so they have easier access to the WebCore namespace.
    117 
    118 static bool supportsFocus(ControlPart appearance)
    119 {
    120     switch (appearance) {
    121     case PushButtonPart:
    122     case ButtonPart:
    123     case DefaultButtonPart:
    124     case SearchFieldPart:
    125     case TextFieldPart:
    126     case TextAreaPart:
    127         return true;
    128     }
    129     return false;
    130 }
    131 
    132 // Return the height of system font |font| in pixels.  We use this size by
    133 // default for some non-form-control elements.
    134 static float systemFontSize(const LOGFONT& font)
    135 {
    136     float size = -font.lfHeight;
    137     if (size < 0) {
    138         HFONT hFont = CreateFontIndirect(&font);
    139         if (hFont) {
    140             HDC hdc = GetDC(0);  // What about printing?  Is this the right DC?
    141             if (hdc) {
    142                 HGDIOBJ hObject = SelectObject(hdc, hFont);
    143                 TEXTMETRIC tm;
    144                 GetTextMetrics(hdc, &tm);
    145                 SelectObject(hdc, hObject);
    146                 ReleaseDC(0, hdc);
    147                 size = tm.tmAscent;
    148             }
    149             DeleteObject(hFont);
    150         }
    151     }
    152 
    153     // The "codepage 936" bit here is from Gecko; apparently this helps make
    154     // fonts more legible in Simplified Chinese where the default font size is
    155     // too small.
    156     //
    157     // FIXME: http://b/1119883 Since this is only used for "small caption",
    158     // "menu", and "status bar" objects, I'm not sure how much this even
    159     // matters.  Plus the Gecko patch went in back in 2002, and maybe this
    160     // isn't even relevant anymore.  We should investigate whether this should
    161     // be removed, or perhaps broadened to be "any CJK locale".
    162     //
    163     return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
    164 }
    165 
    166 // Converts |points| to pixels.  One point is 1/72 of an inch.
    167 static float pointsToPixels(float points)
    168 {
    169     static float pixelsPerInch = 0.0f;
    170     if (!pixelsPerInch) {
    171         HDC hdc = GetDC(0);  // What about printing?  Is this the right DC?
    172         if (hdc) {  // Can this ever actually be NULL?
    173             pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
    174             ReleaseDC(0, hdc);
    175         } else {
    176             pixelsPerInch = 96.0f;
    177         }
    178     }
    179 
    180     static const float pointsPerInch = 72.0f;
    181     return points / pointsPerInch * pixelsPerInch;
    182 }
    183 
    184 static double querySystemBlinkInterval(double defaultInterval)
    185 {
    186     UINT blinkTime = GetCaretBlinkTime();
    187     if (blinkTime == 0)
    188         return defaultInterval;
    189     if (blinkTime == INFINITE)
    190         return 0;
    191     return blinkTime / 1000.0;
    192 }
    193 
    194 PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
    195 {
    196     return adoptRef(new RenderThemeChromiumWin);
    197 }
    198 
    199 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
    200 {
    201     static RenderTheme* rt = RenderThemeChromiumWin::create().releaseRef();
    202     return rt;
    203 }
    204 
    205 bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
    206 {
    207     // Let webkit draw one of its halo rings around any focused element,
    208     // except push buttons. For buttons we use the windows PBS_DEFAULTED
    209     // styling to give it a blue border.
    210     return style->appearance() == ButtonPart
    211             || style->appearance() == PushButtonPart;
    212 }
    213 
    214 Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
    215 {
    216     if (ChromiumBridge::layoutTestMode())
    217         return Color(0x00, 0x00, 0xff);  // Royal blue.
    218     COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
    219     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
    220 }
    221 
    222 Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
    223 {
    224     if (ChromiumBridge::layoutTestMode())
    225         return Color(0x99, 0x99, 0x99);  // Medium gray.
    226     COLORREF color = GetSysColor(COLOR_GRAYTEXT);
    227     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
    228 }
    229 
    230 Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
    231 {
    232     if (ChromiumBridge::layoutTestMode())
    233         return Color(0xff, 0xff, 0xcc);  // Pale yellow.
    234     COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
    235     return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
    236 }
    237 
    238 Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
    239 {
    240     return Color::white;
    241 }
    242 
    243 Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
    244 {
    245     return Color(0xff, 0x96, 0x32);  // Orange.
    246 }
    247 
    248 Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
    249 {
    250     return Color(0xff, 0xff, 0x96); // Yellow.
    251 }
    252 
    253 void RenderThemeChromiumWin::systemFont(int propId, FontDescription& fontDescription) const
    254 {
    255     // This logic owes much to RenderThemeSafari.cpp.
    256     FontDescription* cachedDesc = 0;
    257     AtomicString faceName;
    258     float fontSize = 0;
    259     switch (propId) {
    260     case CSSValueSmallCaption:
    261         cachedDesc = &smallSystemFont;
    262         if (!smallSystemFont.isAbsoluteSize()) {
    263             NONCLIENTMETRICS metrics;
    264             getNonClientMetrics(&metrics);
    265             faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
    266             fontSize = systemFontSize(metrics.lfSmCaptionFont);
    267         }
    268         break;
    269     case CSSValueMenu:
    270         cachedDesc = &menuFont;
    271         if (!menuFont.isAbsoluteSize()) {
    272             NONCLIENTMETRICS metrics;
    273             getNonClientMetrics(&metrics);
    274             faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
    275             fontSize = systemFontSize(metrics.lfMenuFont);
    276         }
    277         break;
    278     case CSSValueStatusBar:
    279         cachedDesc = &labelFont;
    280         if (!labelFont.isAbsoluteSize()) {
    281             NONCLIENTMETRICS metrics;
    282             getNonClientMetrics(&metrics);
    283             faceName = metrics.lfStatusFont.lfFaceName;
    284             fontSize = systemFontSize(metrics.lfStatusFont);
    285         }
    286         break;
    287     case CSSValueWebkitMiniControl:
    288     case CSSValueWebkitSmallControl:
    289     case CSSValueWebkitControl:
    290         faceName = defaultGUIFont();
    291         // Why 2 points smaller?  Because that's what Gecko does.
    292         fontSize = defaultFontSize - pointsToPixels(2);
    293         break;
    294     default:
    295         faceName = defaultGUIFont();
    296         fontSize = defaultFontSize;
    297         break;
    298     }
    299 
    300     if (!cachedDesc)
    301         cachedDesc = &fontDescription;
    302 
    303     if (fontSize) {
    304         cachedDesc->firstFamily().setFamily(faceName);
    305         cachedDesc->setIsAbsoluteSize(true);
    306         cachedDesc->setGenericFamily(FontDescription::NoFamily);
    307         cachedDesc->setSpecifiedSize(fontSize);
    308         cachedDesc->setWeight(FontWeightNormal);
    309         cachedDesc->setItalic(false);
    310     }
    311     fontDescription = *cachedDesc;
    312 }
    313 
    314 // Map a CSSValue* system color to an index understood by GetSysColor().
    315 static int cssValueIdToSysColorIndex(int cssValueId)
    316 {
    317     switch (cssValueId) {
    318     case CSSValueActiveborder: return COLOR_ACTIVEBORDER;
    319     case CSSValueActivecaption: return COLOR_ACTIVECAPTION;
    320     case CSSValueAppworkspace: return COLOR_APPWORKSPACE;
    321     case CSSValueBackground: return COLOR_BACKGROUND;
    322     case CSSValueButtonface: return COLOR_BTNFACE;
    323     case CSSValueButtonhighlight: return COLOR_BTNHIGHLIGHT;
    324     case CSSValueButtonshadow: return COLOR_BTNSHADOW;
    325     case CSSValueButtontext: return COLOR_BTNTEXT;
    326     case CSSValueCaptiontext: return COLOR_CAPTIONTEXT;
    327     case CSSValueGraytext: return COLOR_GRAYTEXT;
    328     case CSSValueHighlight: return COLOR_HIGHLIGHT;
    329     case CSSValueHighlighttext: return COLOR_HIGHLIGHTTEXT;
    330     case CSSValueInactiveborder: return COLOR_INACTIVEBORDER;
    331     case CSSValueInactivecaption: return COLOR_INACTIVECAPTION;
    332     case CSSValueInactivecaptiontext: return COLOR_INACTIVECAPTIONTEXT;
    333     case CSSValueInfobackground: return COLOR_INFOBK;
    334     case CSSValueInfotext: return COLOR_INFOTEXT;
    335     case CSSValueMenu: return COLOR_MENU;
    336     case CSSValueMenutext: return COLOR_MENUTEXT;
    337     case CSSValueScrollbar: return COLOR_SCROLLBAR;
    338     case CSSValueThreeddarkshadow: return COLOR_3DDKSHADOW;
    339     case CSSValueThreedface: return COLOR_3DFACE;
    340     case CSSValueThreedhighlight: return COLOR_3DHIGHLIGHT;
    341     case CSSValueThreedlightshadow: return COLOR_3DLIGHT;
    342     case CSSValueThreedshadow: return COLOR_3DSHADOW;
    343     case CSSValueWindow: return COLOR_WINDOW;
    344     case CSSValueWindowframe: return COLOR_WINDOWFRAME;
    345     case CSSValueWindowtext: return COLOR_WINDOWTEXT;
    346     default: return -1; // Unsupported CSSValue
    347     }
    348 }
    349 
    350 Color RenderThemeChromiumWin::systemColor(int cssValueId) const
    351 {
    352     int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
    353     if (ChromiumBridge::layoutTestMode() || (sysColorIndex == -1))
    354         return RenderTheme::systemColor(cssValueId);
    355 
    356     COLORREF color = GetSysColor(sysColorIndex);
    357     return Color(GetRValue(color), GetGValue(color), GetBValue(color));
    358 }
    359 
    360 void RenderThemeChromiumWin::adjustSliderThumbSize(RenderObject* o) const
    361 {
    362     // These sizes match what WinXP draws for various menus.
    363     const int sliderThumbAlongAxis = 11;
    364     const int sliderThumbAcrossAxis = 21;
    365     if (o->style()->appearance() == SliderThumbHorizontalPart) {
    366         o->style()->setWidth(Length(sliderThumbAlongAxis, Fixed));
    367         o->style()->setHeight(Length(sliderThumbAcrossAxis, Fixed));
    368     } else if (o->style()->appearance() == SliderThumbVerticalPart) {
    369         o->style()->setWidth(Length(sliderThumbAcrossAxis, Fixed));
    370         o->style()->setHeight(Length(sliderThumbAlongAxis, Fixed));
    371     } else
    372         RenderThemeChromiumSkia::adjustSliderThumbSize(o);
    373 }
    374 
    375 bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    376 {
    377     return paintButton(o, i, r);
    378 }
    379 bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    380 {
    381     return paintButton(o, i, r);
    382 }
    383 
    384 bool RenderThemeChromiumWin::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    385 {
    386     const ThemeData& themeData = getThemeData(o);
    387 
    388     WebCore::ThemePainter painter(i.context, r);
    389     ChromiumBridge::paintButton(painter.context(),
    390                                 themeData.m_part,
    391                                 themeData.m_state,
    392                                 themeData.m_classicState,
    393                                 painter.drawRect());
    394     return false;
    395 }
    396 
    397 bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    398 {
    399     return paintTextFieldInternal(o, i, r, true);
    400 }
    401 
    402 bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    403 {
    404     const ThemeData& themeData = getThemeData(o);
    405 
    406     WebCore::ThemePainter painter(i.context, r);
    407     ChromiumBridge::paintTrackbar(painter.context(),
    408                                   themeData.m_part,
    409                                   themeData.m_state,
    410                                   themeData.m_classicState,
    411                                   painter.drawRect());
    412     return false;
    413 }
    414 
    415 bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    416 {
    417     return paintSliderTrack(o, i, r);
    418 }
    419 
    420 // Used to paint unstyled menulists (i.e. with the default border)
    421 bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r)
    422 {
    423     if (!o->isBox())
    424         return false;
    425 
    426     const RenderBox* box = toRenderBox(o);
    427     int borderRight = box->borderRight();
    428     int borderLeft = box->borderLeft();
    429     int borderTop = box->borderTop();
    430     int borderBottom = box->borderBottom();
    431 
    432     // If all the borders are 0, then tell skia not to paint the border on the
    433     // textfield.  FIXME: http://b/1210017 Figure out how to get Windows to not
    434     // draw individual borders and then pass that to skia so we can avoid
    435     // drawing any borders that are set to 0. For non-zero borders, we draw the
    436     // border, but webkit just draws over it.
    437     bool drawEdges = !(borderRight == 0 && borderLeft == 0 && borderTop == 0 && borderBottom == 0);
    438 
    439     paintTextFieldInternal(o, i, r, drawEdges);
    440 
    441     // Take padding and border into account.  If the MenuList is smaller than
    442     // the size of a button, make sure to shrink it appropriately and not put
    443     // its x position to the left of the menulist.
    444     const int buttonWidth = GetSystemMetrics(SM_CXVSCROLL);
    445     int spacingLeft = borderLeft + box->paddingLeft();
    446     int spacingRight = borderRight + box->paddingRight();
    447     int spacingTop = borderTop + box->paddingTop();
    448     int spacingBottom = borderBottom + box->paddingBottom();
    449 
    450     int buttonX;
    451     if (r.right() - r.x() < buttonWidth)
    452         buttonX = r.x();
    453     else
    454         buttonX = o->style()->direction() == LTR ? r.right() - spacingRight - buttonWidth : r.x() + spacingLeft;
    455 
    456     // Compute the rectangle of the button in the destination image.
    457     IntRect rect(buttonX,
    458                  r.y() + spacingTop,
    459                  std::min(buttonWidth, r.right() - r.x()),
    460                  r.height() - (spacingTop + spacingBottom));
    461 
    462     // Get the correct theme data for a textfield and paint the menu.
    463     WebCore::ThemePainter painter(i.context, rect);
    464     ChromiumBridge::paintMenuList(painter.context(),
    465                                   CP_DROPDOWNBUTTON,
    466                                   determineState(o),
    467                                   determineClassicState(o),
    468                                   painter.drawRect());
    469     return false;
    470 }
    471 
    472 // static
    473 void RenderThemeChromiumWin::setDefaultFontSize(int fontSize)
    474 {
    475     RenderThemeChromiumSkia::setDefaultFontSize(fontSize);
    476 
    477     // Reset cached fonts.
    478     smallSystemFont = menuFont = labelFont = FontDescription();
    479 }
    480 
    481 double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
    482 {
    483     // This involves a system call, so we cache the result.
    484     static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
    485     return blinkInterval;
    486 }
    487 
    488 unsigned RenderThemeChromiumWin::determineState(RenderObject* o)
    489 {
    490     unsigned result = TS_NORMAL;
    491     ControlPart appearance = o->style()->appearance();
    492     if (!isEnabled(o))
    493         result = TS_DISABLED;
    494     else if (isReadOnlyControl(o) && (TextFieldPart == appearance || TextAreaPart == appearance || SearchFieldPart == appearance))
    495         result = ETS_READONLY; // Readonly is supported on textfields.
    496     else if (isPressed(o)) // Active overrides hover and focused.
    497         result = TS_PRESSED;
    498     else if (supportsFocus(appearance) && isFocused(o))
    499         result = ETS_FOCUSED;
    500     else if (isHovered(o))
    501         result = TS_HOT;
    502     if (isChecked(o))
    503         result += 4; // 4 unchecked states, 4 checked states.
    504     return result;
    505 }
    506 
    507 unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
    508 {
    509     unsigned result = TUS_NORMAL;
    510     if (!isEnabled(o->parent()))
    511         result = TUS_DISABLED;
    512     else if (supportsFocus(o->style()->appearance()) && isFocused(o->parent()))
    513         result = TUS_FOCUSED;
    514     else if (toRenderSlider(o->parent())->inDragMode())
    515         result = TUS_PRESSED;
    516     else if (isHovered(o))
    517         result = TUS_HOT;
    518     return result;
    519 }
    520 
    521 unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o)
    522 {
    523     unsigned result = 0;
    524 
    525     ControlPart part = o->style()->appearance();
    526 
    527     // Sliders are always in the normal state.
    528     if (part == SliderHorizontalPart || part == SliderVerticalPart)
    529         return result;
    530 
    531     // So are readonly text fields.
    532     if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart))
    533         return result;
    534 
    535     if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
    536         if (!isEnabled(o->parent()))
    537             result = DFCS_INACTIVE;
    538         else if (toRenderSlider(o->parent())->inDragMode()) // Active supersedes hover
    539             result = DFCS_PUSHED;
    540         else if (isHovered(o))
    541             result = DFCS_HOT;
    542     } else {
    543         if (!isEnabled(o))
    544             result = DFCS_INACTIVE;
    545         else if (isPressed(o)) // Active supersedes hover
    546             result = DFCS_PUSHED;
    547         else if (supportsFocus(part) && isFocused(o)) // So does focused
    548             result = 0;
    549         else if (isHovered(o))
    550             result = DFCS_HOT;
    551         if (isChecked(o))
    552             result |= DFCS_CHECKED;
    553     }
    554     return result;
    555 }
    556 
    557 ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o)
    558 {
    559     ThemeData result;
    560     switch (o->style()->appearance()) {
    561     case CheckboxPart:
    562         result.m_part = BP_CHECKBOX;
    563         result.m_state = determineState(o);
    564         result.m_classicState = DFCS_BUTTONCHECK;
    565         break;
    566     case RadioPart:
    567         result.m_part = BP_RADIOBUTTON;
    568         result.m_state = determineState(o);
    569         result.m_classicState = DFCS_BUTTONRADIO;
    570         break;
    571     case PushButtonPart:
    572     case ButtonPart:
    573         result.m_part = BP_PUSHBUTTON;
    574         result.m_state = determineState(o);
    575         result.m_classicState = DFCS_BUTTONPUSH;
    576         break;
    577     case SliderHorizontalPart:
    578         result.m_part = TKP_TRACK;
    579         result.m_state = TRS_NORMAL;
    580         break;
    581     case SliderVerticalPart:
    582         result.m_part = TKP_TRACKVERT;
    583         result.m_state = TRVS_NORMAL;
    584         break;
    585     case SliderThumbHorizontalPart:
    586         result.m_part = TKP_THUMBBOTTOM;
    587         result.m_state = determineSliderThumbState(o);
    588         break;
    589     case SliderThumbVerticalPart:
    590         result.m_part = TKP_THUMBVERT;
    591         result.m_state = determineSliderThumbState(o);
    592         break;
    593     case ListboxPart:
    594     case MenulistPart:
    595     case MenulistButtonPart:
    596     case SearchFieldPart:
    597     case TextFieldPart:
    598     case TextAreaPart:
    599         result.m_part = EP_EDITTEXT;
    600         result.m_state = determineState(o);
    601         break;
    602     }
    603 
    604     result.m_classicState |= determineClassicState(o);
    605 
    606     return result;
    607 }
    608 
    609 bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
    610                                                     const RenderObject::PaintInfo& i,
    611                                                     const IntRect& r,
    612                                                     bool drawEdges)
    613 {
    614     // Fallback to white if the specified color object is invalid.
    615     // (Note ChromiumBridge::paintTextField duplicates this check).
    616     Color backgroundColor(Color::white);
    617     if (o->style()->backgroundColor().isValid())
    618         backgroundColor = o->style()->backgroundColor();
    619 
    620     // If we have background-image, don't fill the content area to expose the
    621     // parent's background. Also, we shouldn't fill the content area if the
    622     // alpha of the color is 0. The API of Windows GDI ignores the alpha.
    623     //
    624     // Note that we should paint the content area white if we have neither the
    625     // background color nor background image explicitly specified to keep the
    626     // appearance of select element consistent with other browsers.
    627     bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
    628 
    629     if (o->style()->hasBorderRadius()) {
    630         // If the style has rounded borders, setup the context to clip the
    631         // background (themed or filled) appropriately.
    632         // FIXME: make sure we do the right thing if css background-clip is set.
    633         i.context->save();
    634         IntSize topLeft, topRight, bottomLeft, bottomRight;
    635         o->style()->getBorderRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight);
    636         i.context->addRoundedRectClip(r, topLeft, topRight, bottomLeft, bottomRight);
    637     }
    638     {
    639         const ThemeData& themeData = getThemeData(o);
    640         WebCore::ThemePainter painter(i.context, r);
    641         ChromiumBridge::paintTextField(painter.context(),
    642                                        themeData.m_part,
    643                                        themeData.m_state,
    644                                        themeData.m_classicState,
    645                                        painter.drawRect(),
    646                                        backgroundColor,
    647                                        fillContentArea,
    648                                        drawEdges);
    649         // End of block commits the painter before restoring context.
    650     }
    651     if (o->style()->hasBorderRadius())
    652         i.context->restore();
    653     return false;
    654 }
    655 
    656 } // namespace WebCore
    657