Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2007 Apple Inc.
      3  * Copyright (C) 2007 Alp Toker <alp (at) atoker.com>
      4  * Copyright (C) 2008 Collabora Ltd.
      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., 51 Franklin Street, Fifth Floor,
     21  * Boston, MA 02110-1301, USA.
     22  *
     23  */
     24 
     25 #include "config.h"
     26 #include "core/rendering/RenderThemeChromiumDefault.h"
     27 
     28 #include "core/CSSValueKeywords.h"
     29 #include "core/UserAgentStyleSheets.h"
     30 #include "core/rendering/PaintInfo.h"
     31 #include "core/rendering/RenderObject.h"
     32 #include "core/rendering/RenderProgress.h"
     33 #include "platform/LayoutTestSupport.h"
     34 #include "platform/graphics/Color.h"
     35 #include "platform/graphics/GraphicsContext.h"
     36 #include "platform/graphics/GraphicsContextStateSaver.h"
     37 #include "public/platform/Platform.h"
     38 #include "public/platform/WebRect.h"
     39 #include "public/platform/WebThemeEngine.h"
     40 #include "wtf/StdLibExtras.h"
     41 
     42 namespace blink {
     43 
     44 static bool useMockTheme()
     45 {
     46     return LayoutTestSupport::isRunningLayoutTest();
     47 }
     48 
     49 unsigned RenderThemeChromiumDefault::m_activeSelectionBackgroundColor =
     50     0xff1e90ff;
     51 unsigned RenderThemeChromiumDefault::m_activeSelectionForegroundColor =
     52     Color::black;
     53 unsigned RenderThemeChromiumDefault::m_inactiveSelectionBackgroundColor =
     54     0xffc8c8c8;
     55 unsigned RenderThemeChromiumDefault::m_inactiveSelectionForegroundColor =
     56     0xff323232;
     57 
     58 double RenderThemeChromiumDefault::m_caretBlinkInterval;
     59 
     60 static const unsigned defaultButtonBackgroundColor = 0xffdddddd;
     61 
     62 static WebThemeEngine::State getWebThemeState(const RenderTheme* theme, const RenderObject* o)
     63 {
     64     if (!theme->isEnabled(o))
     65         return WebThemeEngine::StateDisabled;
     66     if (useMockTheme() && theme->isReadOnlyControl(o))
     67         return WebThemeEngine::StateReadonly;
     68     if (theme->isPressed(o))
     69         return WebThemeEngine::StatePressed;
     70     if (useMockTheme() && theme->isFocused(o))
     71         return WebThemeEngine::StateFocused;
     72     if (theme->isHovered(o))
     73         return WebThemeEngine::StateHover;
     74 
     75     return WebThemeEngine::StateNormal;
     76 }
     77 
     78 PassRefPtr<RenderTheme> RenderThemeChromiumDefault::create()
     79 {
     80     return adoptRef(new RenderThemeChromiumDefault());
     81 }
     82 
     83 // RenderTheme::theme for Android is defined in RenderThemeChromiumAndroid.cpp.
     84 #if !OS(ANDROID)
     85 RenderTheme& RenderTheme::theme()
     86 {
     87     DEFINE_STATIC_REF(RenderTheme, renderTheme, (RenderThemeChromiumDefault::create()));
     88     return *renderTheme;
     89 }
     90 #endif
     91 
     92 RenderThemeChromiumDefault::RenderThemeChromiumDefault()
     93 {
     94     m_caretBlinkInterval = RenderTheme::caretBlinkInterval();
     95 }
     96 
     97 RenderThemeChromiumDefault::~RenderThemeChromiumDefault()
     98 {
     99 }
    100 
    101 bool RenderThemeChromiumDefault::supportsFocusRing(const RenderStyle* style) const
    102 {
    103     if (useMockTheme()) {
    104         // Don't use focus rings for buttons when mocking controls.
    105         return style->appearance() == ButtonPart
    106             || style->appearance() == PushButtonPart
    107             || style->appearance() == SquareButtonPart;
    108     }
    109 
    110     return RenderThemeChromiumSkia::supportsFocusRing(style);
    111 }
    112 
    113 Color RenderThemeChromiumDefault::systemColor(CSSValueID cssValueId) const
    114 {
    115     static const Color defaultButtonGrayColor(0xffdddddd);
    116     static const Color defaultMenuColor(0xfff7f7f7);
    117 
    118     if (cssValueId == CSSValueButtonface) {
    119         if (useMockTheme())
    120             return Color(0xc0, 0xc0, 0xc0);
    121         return defaultButtonGrayColor;
    122     }
    123     if (cssValueId == CSSValueMenu)
    124         return defaultMenuColor;
    125     return RenderTheme::systemColor(cssValueId);
    126 }
    127 
    128 String RenderThemeChromiumDefault::extraDefaultStyleSheet()
    129 {
    130     // FIXME: We should not have OS() branches here.
    131     // We should have something like RenderThemeWin, RenderThemeLinux, or
    132     // should concatenate UA stylesheets on build time.
    133 #if !OS(WIN)
    134     return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
    135 #if !OS(ANDROID)
    136         String(themeInputMultipleFieldsCss, sizeof(themeInputMultipleFieldsCss)) +
    137 #endif
    138         String(themeChromiumLinuxCss, sizeof(themeChromiumLinuxCss));
    139 #else
    140     return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
    141         String(themeInputMultipleFieldsCss, sizeof(themeInputMultipleFieldsCss));
    142 #endif
    143 }
    144 
    145 Color RenderThemeChromiumDefault::activeListBoxSelectionBackgroundColor() const
    146 {
    147     return Color(0x28, 0x28, 0x28);
    148 }
    149 
    150 Color RenderThemeChromiumDefault::activeListBoxSelectionForegroundColor() const
    151 {
    152     return Color::black;
    153 }
    154 
    155 Color RenderThemeChromiumDefault::inactiveListBoxSelectionBackgroundColor() const
    156 {
    157     return Color(0xc8, 0xc8, 0xc8);
    158 }
    159 
    160 Color RenderThemeChromiumDefault::inactiveListBoxSelectionForegroundColor() const
    161 {
    162     return Color(0x32, 0x32, 0x32);
    163 }
    164 
    165 Color RenderThemeChromiumDefault::platformActiveSelectionBackgroundColor() const
    166 {
    167     if (useMockTheme())
    168         return Color(0x00, 0x00, 0xff); // Royal blue.
    169     return m_activeSelectionBackgroundColor;
    170 }
    171 
    172 Color RenderThemeChromiumDefault::platformInactiveSelectionBackgroundColor() const
    173 {
    174     if (useMockTheme())
    175         return Color(0x99, 0x99, 0x99); // Medium gray.
    176     return m_inactiveSelectionBackgroundColor;
    177 }
    178 
    179 Color RenderThemeChromiumDefault::platformActiveSelectionForegroundColor() const
    180 {
    181     if (useMockTheme())
    182         return Color(0xff, 0xff, 0xcc); // Pale yellow.
    183     return m_activeSelectionForegroundColor;
    184 }
    185 
    186 Color RenderThemeChromiumDefault::platformInactiveSelectionForegroundColor() const
    187 {
    188     if (useMockTheme())
    189         return Color::white;
    190     return m_inactiveSelectionForegroundColor;
    191 }
    192 
    193 IntSize RenderThemeChromiumDefault::sliderTickSize() const
    194 {
    195     if (useMockTheme())
    196         return IntSize(1, 3);
    197     return IntSize(1, 6);
    198 }
    199 
    200 int RenderThemeChromiumDefault::sliderTickOffsetFromTrackCenter() const
    201 {
    202     if (useMockTheme())
    203         return 11;
    204     return -16;
    205 }
    206 
    207 void RenderThemeChromiumDefault::adjustSliderThumbSize(RenderStyle* style, Element* element) const
    208 {
    209     IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartSliderThumb);
    210 
    211     // FIXME: Mock theme doesn't handle zoomed sliders.
    212     float zoomLevel = useMockTheme() ? 1 : style->effectiveZoom();
    213     if (style->appearance() == SliderThumbHorizontalPart) {
    214         style->setWidth(Length(size.width() * zoomLevel, Fixed));
    215         style->setHeight(Length(size.height() * zoomLevel, Fixed));
    216     } else if (style->appearance() == SliderThumbVerticalPart) {
    217         style->setWidth(Length(size.height() * zoomLevel, Fixed));
    218         style->setHeight(Length(size.width() * zoomLevel, Fixed));
    219     } else
    220         RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
    221 }
    222 
    223 void RenderThemeChromiumDefault::setCaretBlinkInterval(double interval)
    224 {
    225     m_caretBlinkInterval = interval;
    226 }
    227 
    228 double RenderThemeChromiumDefault::caretBlinkIntervalInternal() const
    229 {
    230     return m_caretBlinkInterval;
    231 }
    232 
    233 void RenderThemeChromiumDefault::setSelectionColors(
    234     unsigned activeBackgroundColor,
    235     unsigned activeForegroundColor,
    236     unsigned inactiveBackgroundColor,
    237     unsigned inactiveForegroundColor)
    238 {
    239     m_activeSelectionBackgroundColor = activeBackgroundColor;
    240     m_activeSelectionForegroundColor = activeForegroundColor;
    241     m_inactiveSelectionBackgroundColor = inactiveBackgroundColor;
    242     m_inactiveSelectionForegroundColor = inactiveForegroundColor;
    243 }
    244 
    245 bool RenderThemeChromiumDefault::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    246 {
    247     WebThemeEngine::ExtraParams extraParams;
    248     WebCanvas* canvas = i.context->canvas();
    249     extraParams.button.checked = isChecked(o);
    250     extraParams.button.indeterminate = isIndeterminate(o);
    251 
    252     float zoomLevel = o->style()->effectiveZoom();
    253     GraphicsContextStateSaver stateSaver(*i.context, false);
    254     IntRect unzoomedRect = rect;
    255     if (zoomLevel != 1) {
    256         stateSaver.save();
    257         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
    258         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
    259         i.context->translate(unzoomedRect.x(), unzoomedRect.y());
    260         i.context->scale(zoomLevel, zoomLevel);
    261         i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
    262     }
    263 
    264     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartCheckbox, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams);
    265     return false;
    266 }
    267 
    268 void RenderThemeChromiumDefault::setCheckboxSize(RenderStyle* style) const
    269 {
    270     // If the width and height are both specified, then we have nothing to do.
    271     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
    272         return;
    273 
    274     IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartCheckbox);
    275     float zoomLevel = style->effectiveZoom();
    276     size.setWidth(size.width() * zoomLevel);
    277     size.setHeight(size.height() * zoomLevel);
    278     setSizeIfAuto(style, size);
    279 }
    280 
    281 bool RenderThemeChromiumDefault::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    282 {
    283     WebThemeEngine::ExtraParams extraParams;
    284     WebCanvas* canvas = i.context->canvas();
    285     extraParams.button.checked = isChecked(o);
    286 
    287     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartRadio, getWebThemeState(this, o), WebRect(rect), &extraParams);
    288     return false;
    289 }
    290 
    291 void RenderThemeChromiumDefault::setRadioSize(RenderStyle* style) const
    292 {
    293     // If the width and height are both specified, then we have nothing to do.
    294     if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto())
    295         return;
    296 
    297     IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartRadio);
    298     float zoomLevel = style->effectiveZoom();
    299     size.setWidth(size.width() * zoomLevel);
    300     size.setHeight(size.height() * zoomLevel);
    301     setSizeIfAuto(style, size);
    302 }
    303 
    304 bool RenderThemeChromiumDefault::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    305 {
    306     WebThemeEngine::ExtraParams extraParams;
    307     WebCanvas* canvas = i.context->canvas();
    308     extraParams.button.hasBorder = true;
    309     extraParams.button.backgroundColor = useMockTheme() ? 0xffc0c0c0 : defaultButtonBackgroundColor;
    310     if (o->hasBackground())
    311         extraParams.button.backgroundColor = o->resolveColor(CSSPropertyBackgroundColor).rgb();
    312 
    313     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartButton, getWebThemeState(this, o), WebRect(rect), &extraParams);
    314     return false;
    315 }
    316 
    317 bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    318 {
    319     // WebThemeEngine does not handle border rounded corner and background image
    320     // so return true to draw CSS border and background.
    321     if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage())
    322         return true;
    323 
    324     ControlPart part = o->style()->appearance();
    325 
    326     WebThemeEngine::ExtraParams extraParams;
    327     extraParams.textField.isTextArea = part == TextAreaPart;
    328     extraParams.textField.isListbox = part == ListboxPart;
    329 
    330     WebCanvas* canvas = i.context->canvas();
    331 
    332     Color backgroundColor = o->resolveColor(CSSPropertyBackgroundColor);
    333     extraParams.textField.backgroundColor = backgroundColor.rgb();
    334 
    335     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartTextField, getWebThemeState(this, o), WebRect(rect), &extraParams);
    336     return false;
    337 }
    338 
    339 bool RenderThemeChromiumDefault::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    340 {
    341     if (!o->isBox())
    342         return false;
    343 
    344     const int right = rect.x() + rect.width();
    345     const int middle = rect.y() + rect.height() / 2;
    346 
    347     WebThemeEngine::ExtraParams extraParams;
    348     extraParams.menuList.arrowY = middle;
    349     const RenderBox* box = toRenderBox(o);
    350     // Match Chromium Win behaviour of showing all borders if any are shown.
    351     extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() || box->borderTop() || box->borderBottom();
    352     extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
    353     // Fallback to transparent if the specified color object is invalid.
    354     Color backgroundColor(Color::transparent);
    355     if (o->hasBackground())
    356         backgroundColor = o->resolveColor(CSSPropertyBackgroundColor);
    357     extraParams.menuList.backgroundColor = backgroundColor.rgb();
    358 
    359     // If we have a background image, don't fill the content area to expose the
    360     // parent's background. Also, we shouldn't fill the content area if the
    361     // alpha of the color is 0. The API of Windows GDI ignores the alpha.
    362     // FIXME: the normal Aura theme doesn't care about this, so we should
    363     // investigate if we really need fillContentArea.
    364     extraParams.menuList.fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
    365 
    366     if (useMockTheme()) {
    367         // The size and position of the drop-down button is different between
    368         // the mock theme and the regular aura theme.
    369         int spacingTop = box->borderTop() + box->paddingTop();
    370         int spacingBottom = box->borderBottom() + box->paddingBottom();
    371         int spacingRight = box->borderRight() + box->paddingRight();
    372         extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 4 + spacingRight: right - 13 - spacingRight;
    373         extraParams.menuList.arrowHeight = rect.height() - spacingBottom - spacingTop;
    374     } else {
    375         extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
    376     }
    377 
    378     WebCanvas* canvas = i.context->canvas();
    379 
    380     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartMenuList, getWebThemeState(this, o), WebRect(rect), &extraParams);
    381     return false;
    382 }
    383 
    384 bool RenderThemeChromiumDefault::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    385 {
    386     if (!o->isBox())
    387         return false;
    388 
    389     const int right = rect.x() + rect.width();
    390     const int middle = rect.y() + rect.height() / 2;
    391 
    392     WebThemeEngine::ExtraParams extraParams;
    393     extraParams.menuList.arrowY = middle;
    394     extraParams.menuList.hasBorder = false;
    395     extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
    396     extraParams.menuList.backgroundColor = Color::transparent;
    397     extraParams.menuList.fillContentArea = false;
    398 
    399     if (useMockTheme()) {
    400         const RenderBox* box = toRenderBox(o);
    401         // The size and position of the drop-down button is different between
    402         // the mock theme and the regular aura theme.
    403         int spacingTop = box->borderTop() + box->paddingTop();
    404         int spacingBottom = box->borderBottom() + box->paddingBottom();
    405         int spacingRight = box->borderRight() + box->paddingRight();
    406         extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 4 + spacingRight: right - 13 - spacingRight;
    407         extraParams.menuList.arrowHeight = rect.height() - spacingBottom - spacingTop;
    408     } else {
    409         extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
    410     }
    411 
    412     WebCanvas* canvas = i.context->canvas();
    413 
    414     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartMenuList, getWebThemeState(this, o), WebRect(rect), &extraParams);
    415     return false;
    416 }
    417 
    418 bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    419 {
    420     WebThemeEngine::ExtraParams extraParams;
    421     WebCanvas* canvas = i.context->canvas();
    422     extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart;
    423 
    424     paintSliderTicks(o, i, rect);
    425 
    426     // FIXME: Mock theme doesn't handle zoomed sliders.
    427     float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom();
    428     GraphicsContextStateSaver stateSaver(*i.context, false);
    429     IntRect unzoomedRect = rect;
    430     if (zoomLevel != 1) {
    431         stateSaver.save();
    432         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
    433         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
    434         i.context->translate(unzoomedRect.x(), unzoomedRect.y());
    435         i.context->scale(zoomLevel, zoomLevel);
    436         i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
    437     }
    438 
    439     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartSliderTrack, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams);
    440 
    441     return false;
    442 }
    443 
    444 bool RenderThemeChromiumDefault::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    445 {
    446     WebThemeEngine::ExtraParams extraParams;
    447     WebCanvas* canvas = i.context->canvas();
    448     extraParams.slider.vertical = o->style()->appearance() == SliderThumbVerticalPart;
    449     extraParams.slider.inDrag = isPressed(o);
    450 
    451     // FIXME: Mock theme doesn't handle zoomed sliders.
    452     float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom();
    453     GraphicsContextStateSaver stateSaver(*i.context, false);
    454     IntRect unzoomedRect = rect;
    455     if (zoomLevel != 1) {
    456         stateSaver.save();
    457         unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
    458         unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
    459         i.context->translate(unzoomedRect.x(), unzoomedRect.y());
    460         i.context->scale(zoomLevel, zoomLevel);
    461         i.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
    462     }
    463 
    464     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartSliderThumb, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams);
    465     return false;
    466 }
    467 
    468 void RenderThemeChromiumDefault::adjustInnerSpinButtonStyle(RenderStyle* style, Element*) const
    469 {
    470     IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartInnerSpinButton);
    471 
    472     style->setWidth(Length(size.width(), Fixed));
    473     style->setMinWidth(Length(size.width(), Fixed));
    474 }
    475 
    476 bool RenderThemeChromiumDefault::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    477 {
    478     WebThemeEngine::ExtraParams extraParams;
    479     WebCanvas* canvas = i.context->canvas();
    480     extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpControlState);
    481     extraParams.innerSpin.readOnly = isReadOnlyControl(o);
    482 
    483     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartInnerSpinButton, getWebThemeState(this, o), WebRect(rect), &extraParams);
    484     return false;
    485 }
    486 
    487 bool RenderThemeChromiumDefault::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& rect)
    488 {
    489     if (!o->isProgress())
    490         return true;
    491 
    492     RenderProgress* renderProgress = toRenderProgress(o);
    493     IntRect valueRect = progressValueRectFor(renderProgress, rect);
    494 
    495     WebThemeEngine::ExtraParams extraParams;
    496     extraParams.progressBar.determinate = renderProgress->isDeterminate();
    497     extraParams.progressBar.valueRectX = valueRect.x();
    498     extraParams.progressBar.valueRectY = valueRect.y();
    499     extraParams.progressBar.valueRectWidth = valueRect.width();
    500     extraParams.progressBar.valueRectHeight = valueRect.height();
    501 
    502     DirectionFlippingScope scope(o, i, rect);
    503     WebCanvas* canvas = i.context->canvas();
    504     Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartProgressBar, getWebThemeState(this, o), WebRect(rect), &extraParams);
    505     return false;
    506 }
    507 
    508 bool RenderThemeChromiumDefault::shouldOpenPickerWithF4Key() const
    509 {
    510     return true;
    511 }
    512 
    513 bool RenderThemeChromiumDefault::shouldUseFallbackTheme(RenderStyle* style) const
    514 {
    515     if (useMockTheme()) {
    516         // The mock theme can't handle zoomed controls, so we fall back to the "fallback" theme.
    517         ControlPart part = style->appearance();
    518         if (part == CheckboxPart || part == RadioPart)
    519             return style->effectiveZoom() != 1;
    520     }
    521     return RenderTheme::shouldUseFallbackTheme(style);
    522 }
    523 
    524 } // namespace blink
    525