| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007 Apple Inc. | 2 * Copyright (C) 2007 Apple Inc. |
| 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| 4 * Copyright (C) 2008 Collabora Ltd. | 4 * Copyright (C) 2008 Collabora Ltd. |
| 5 * Copyright (C) 2008, 2009 Google Inc. | 5 * Copyright (C) 2008, 2009 Google Inc. |
| 6 * Copyright (C) 2009 Kenneth Rohde Christiansen | 6 * Copyright (C) 2009 Kenneth Rohde Christiansen |
| 7 * | 7 * |
| 8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
| 9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
| 10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
| 11 * version 2 of the License, or (at your option) any later version. | 11 * version 2 of the License, or (at your option) any later version. |
| 12 * | 12 * |
| 13 * This library is distributed in the hope that it will be useful, | 13 * This library is distributed in the hope that it will be useful, |
| 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 * Library General Public License for more details. | 16 * Library General Public License for more details. |
| 17 * | 17 * |
| 18 * You should have received a copy of the GNU Library General Public License | 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 | 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, | 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
| 22 * | 22 * |
| 23 */ | 23 */ |
| 24 | 24 |
| 25 #include "config.h" | 25 #include "config.h" |
| 26 #include "core/layout/LayoutThemeDefault.h" | 26 #include "core/layout/LayoutThemeDefault.h" |
| 27 | 27 |
| 28 #include "core/CSSValueKeywords.h" | 28 #include "core/CSSValueKeywords.h" |
| 29 #include "core/layout/LayoutMediaControls.h" | |
| 30 #include "core/layout/LayoutObject.h" | 29 #include "core/layout/LayoutObject.h" |
| 31 #include "core/layout/LayoutProgress.h" | 30 #include "core/layout/LayoutProgress.h" |
| 32 #include "core/layout/LayoutThemeFontProvider.h" | 31 #include "core/layout/LayoutThemeFontProvider.h" |
| 33 #include "core/paint/PaintInfo.h" | 32 #include "core/paint/MediaControlsPainter.h" |
| 34 #include "platform/LayoutTestSupport.h" | 33 #include "platform/LayoutTestSupport.h" |
| 35 #include "platform/PlatformResourceLoader.h" | 34 #include "platform/PlatformResourceLoader.h" |
| 36 #include "platform/graphics/Color.h" | 35 #include "platform/graphics/Color.h" |
| 37 #include "platform/graphics/GraphicsContext.h" | |
| 38 #include "platform/graphics/GraphicsContextStateSaver.h" | |
| 39 #include "platform/scroll/ScrollbarTheme.h" | 36 #include "platform/scroll/ScrollbarTheme.h" |
| 40 #include "public/platform/Platform.h" | 37 #include "public/platform/Platform.h" |
| 41 #include "public/platform/WebRect.h" | |
| 42 #include "public/platform/WebThemeEngine.h" | 38 #include "public/platform/WebThemeEngine.h" |
| 43 #include "wtf/StdLibExtras.h" | |
| 44 | 39 |
| 45 namespace blink { | 40 namespace blink { |
| 46 | 41 |
| 47 enum PaddingType { | 42 enum PaddingType { |
| 48 TopPadding, | 43 TopPadding, |
| 49 RightPadding, | 44 RightPadding, |
| 50 BottomPadding, | 45 BottomPadding, |
| 51 LeftPadding | 46 LeftPadding |
| 52 }; | 47 }; |
| 53 | 48 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 67 return LayoutTestSupport::isRunningLayoutTest(); | 62 return LayoutTestSupport::isRunningLayoutTest(); |
| 68 } | 63 } |
| 69 | 64 |
| 70 unsigned LayoutThemeDefault::m_activeSelectionBackgroundColor = 0xff1e90ff; | 65 unsigned LayoutThemeDefault::m_activeSelectionBackgroundColor = 0xff1e90ff; |
| 71 unsigned LayoutThemeDefault::m_activeSelectionForegroundColor = Color::black; | 66 unsigned LayoutThemeDefault::m_activeSelectionForegroundColor = Color::black; |
| 72 unsigned LayoutThemeDefault::m_inactiveSelectionBackgroundColor = 0xffc8c8c8; | 67 unsigned LayoutThemeDefault::m_inactiveSelectionBackgroundColor = 0xffc8c8c8; |
| 73 unsigned LayoutThemeDefault::m_inactiveSelectionForegroundColor = 0xff323232; | 68 unsigned LayoutThemeDefault::m_inactiveSelectionForegroundColor = 0xff323232; |
| 74 | 69 |
| 75 double LayoutThemeDefault::m_caretBlinkInterval; | 70 double LayoutThemeDefault::m_caretBlinkInterval; |
| 76 | 71 |
| 77 static const unsigned defaultButtonBackgroundColor = 0xffdddddd; | |
| 78 | |
| 79 static WebThemeEngine::State getWebThemeState(const LayoutTheme* theme, const La
youtObject* o) | |
| 80 { | |
| 81 if (!theme->isEnabled(o)) | |
| 82 return WebThemeEngine::StateDisabled; | |
| 83 if (useMockTheme() && theme->isReadOnlyControl(o)) | |
| 84 return WebThemeEngine::StateReadonly; | |
| 85 if (theme->isPressed(o)) | |
| 86 return WebThemeEngine::StatePressed; | |
| 87 if (useMockTheme() && theme->isFocused(o)) | |
| 88 return WebThemeEngine::StateFocused; | |
| 89 if (theme->isHovered(o)) | |
| 90 return WebThemeEngine::StateHover; | |
| 91 | |
| 92 return WebThemeEngine::StateNormal; | |
| 93 } | |
| 94 | |
| 95 LayoutThemeDefault::LayoutThemeDefault() | 72 LayoutThemeDefault::LayoutThemeDefault() |
| 96 { | 73 { |
| 97 m_caretBlinkInterval = LayoutTheme::caretBlinkInterval(); | 74 m_caretBlinkInterval = LayoutTheme::caretBlinkInterval(); |
| 98 } | 75 } |
| 99 | 76 |
| 100 LayoutThemeDefault::~LayoutThemeDefault() | 77 LayoutThemeDefault::~LayoutThemeDefault() |
| 101 { | 78 { |
| 102 } | 79 } |
| 103 | 80 |
| 104 bool LayoutThemeDefault::supportsFocusRing(const ComputedStyle& style) const | 81 bool LayoutThemeDefault::supportsFocusRing(const ComputedStyle& style) const |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 | 199 |
| 223 // FIXME: Mock theme doesn't handle zoomed sliders. | 200 // FIXME: Mock theme doesn't handle zoomed sliders. |
| 224 float zoomLevel = useMockTheme() ? 1 : style.effectiveZoom(); | 201 float zoomLevel = useMockTheme() ? 1 : style.effectiveZoom(); |
| 225 if (style.appearance() == SliderThumbHorizontalPart) { | 202 if (style.appearance() == SliderThumbHorizontalPart) { |
| 226 style.setWidth(Length(size.width() * zoomLevel, Fixed)); | 203 style.setWidth(Length(size.width() * zoomLevel, Fixed)); |
| 227 style.setHeight(Length(size.height() * zoomLevel, Fixed)); | 204 style.setHeight(Length(size.height() * zoomLevel, Fixed)); |
| 228 } else if (style.appearance() == SliderThumbVerticalPart) { | 205 } else if (style.appearance() == SliderThumbVerticalPart) { |
| 229 style.setWidth(Length(size.height() * zoomLevel, Fixed)); | 206 style.setWidth(Length(size.height() * zoomLevel, Fixed)); |
| 230 style.setHeight(Length(size.width() * zoomLevel, Fixed)); | 207 style.setHeight(Length(size.width() * zoomLevel, Fixed)); |
| 231 } else { | 208 } else { |
| 232 LayoutMediaControls::adjustMediaSliderThumbSize(style); | 209 MediaControlsPainter::adjustMediaSliderThumbSize(style); |
| 233 } | 210 } |
| 234 } | 211 } |
| 235 | 212 |
| 236 void LayoutThemeDefault::setCaretBlinkInterval(double interval) | 213 void LayoutThemeDefault::setCaretBlinkInterval(double interval) |
| 237 { | 214 { |
| 238 m_caretBlinkInterval = interval; | 215 m_caretBlinkInterval = interval; |
| 239 } | 216 } |
| 240 | 217 |
| 241 void LayoutThemeDefault::setSelectionColors( | 218 void LayoutThemeDefault::setSelectionColors( |
| 242 unsigned activeBackgroundColor, | 219 unsigned activeBackgroundColor, |
| 243 unsigned activeForegroundColor, | 220 unsigned activeForegroundColor, |
| 244 unsigned inactiveBackgroundColor, | 221 unsigned inactiveBackgroundColor, |
| 245 unsigned inactiveForegroundColor) | 222 unsigned inactiveForegroundColor) |
| 246 { | 223 { |
| 247 m_activeSelectionBackgroundColor = activeBackgroundColor; | 224 m_activeSelectionBackgroundColor = activeBackgroundColor; |
| 248 m_activeSelectionForegroundColor = activeForegroundColor; | 225 m_activeSelectionForegroundColor = activeForegroundColor; |
| 249 m_inactiveSelectionBackgroundColor = inactiveBackgroundColor; | 226 m_inactiveSelectionBackgroundColor = inactiveBackgroundColor; |
| 250 m_inactiveSelectionForegroundColor = inactiveForegroundColor; | 227 m_inactiveSelectionForegroundColor = inactiveForegroundColor; |
| 251 } | 228 } |
| 252 | 229 |
| 253 bool LayoutThemeDefault::paintCheckbox(LayoutObject* o, const PaintInfo& i, cons
t IntRect& rect) | |
| 254 { | |
| 255 WebThemeEngine::ExtraParams extraParams; | |
| 256 WebCanvas* canvas = i.context->canvas(); | |
| 257 extraParams.button.checked = isChecked(o); | |
| 258 extraParams.button.indeterminate = isIndeterminate(o); | |
| 259 | |
| 260 float zoomLevel = o->style()->effectiveZoom(); | |
| 261 GraphicsContextStateSaver stateSaver(*i.context, false); | |
| 262 IntRect unzoomedRect = rect; | |
| 263 if (zoomLevel != 1) { | |
| 264 stateSaver.save(); | |
| 265 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); | |
| 266 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); | |
| 267 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); | |
| 268 i.context->scale(zoomLevel, zoomLevel); | |
| 269 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); | |
| 270 } | |
| 271 | |
| 272 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartCheckb
ox, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams); | |
| 273 return false; | |
| 274 } | |
| 275 | |
| 276 void LayoutThemeDefault::setCheckboxSize(ComputedStyle& style) const | 230 void LayoutThemeDefault::setCheckboxSize(ComputedStyle& style) const |
| 277 { | 231 { |
| 278 // If the width and height are both specified, then we have nothing to do. | 232 // If the width and height are both specified, then we have nothing to do. |
| 279 if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) | 233 if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) |
| 280 return; | 234 return; |
| 281 | 235 |
| 282 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artCheckbox); | 236 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artCheckbox); |
| 283 float zoomLevel = style.effectiveZoom(); | 237 float zoomLevel = style.effectiveZoom(); |
| 284 size.setWidth(size.width() * zoomLevel); | 238 size.setWidth(size.width() * zoomLevel); |
| 285 size.setHeight(size.height() * zoomLevel); | 239 size.setHeight(size.height() * zoomLevel); |
| 286 setSizeIfAuto(style, size); | 240 setSizeIfAuto(style, size); |
| 287 } | 241 } |
| 288 | 242 |
| 289 bool LayoutThemeDefault::paintRadio(LayoutObject* o, const PaintInfo& i, const I
ntRect& rect) | |
| 290 { | |
| 291 WebThemeEngine::ExtraParams extraParams; | |
| 292 WebCanvas* canvas = i.context->canvas(); | |
| 293 extraParams.button.checked = isChecked(o); | |
| 294 | |
| 295 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartRadio,
getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 296 return false; | |
| 297 } | |
| 298 | |
| 299 void LayoutThemeDefault::setRadioSize(ComputedStyle& style) const | 243 void LayoutThemeDefault::setRadioSize(ComputedStyle& style) const |
| 300 { | 244 { |
| 301 // If the width and height are both specified, then we have nothing to do. | 245 // If the width and height are both specified, then we have nothing to do. |
| 302 if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) | 246 if (!style.width().isIntrinsicOrAuto() && !style.height().isAuto()) |
| 303 return; | 247 return; |
| 304 | 248 |
| 305 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artRadio); | 249 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artRadio); |
| 306 float zoomLevel = style.effectiveZoom(); | 250 float zoomLevel = style.effectiveZoom(); |
| 307 size.setWidth(size.width() * zoomLevel); | 251 size.setWidth(size.width() * zoomLevel); |
| 308 size.setHeight(size.height() * zoomLevel); | 252 size.setHeight(size.height() * zoomLevel); |
| 309 setSizeIfAuto(style, size); | 253 setSizeIfAuto(style, size); |
| 310 } | 254 } |
| 311 | 255 |
| 312 bool LayoutThemeDefault::paintButton(LayoutObject* o, const PaintInfo& i, const
IntRect& rect) | |
| 313 { | |
| 314 WebThemeEngine::ExtraParams extraParams; | |
| 315 WebCanvas* canvas = i.context->canvas(); | |
| 316 extraParams.button.hasBorder = true; | |
| 317 extraParams.button.backgroundColor = useMockTheme() ? 0xffc0c0c0 : defaultBu
ttonBackgroundColor; | |
| 318 if (o->hasBackground()) | |
| 319 extraParams.button.backgroundColor = o->resolveColor(CSSPropertyBackgrou
ndColor).rgb(); | |
| 320 | |
| 321 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartButton
, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 322 return false; | |
| 323 } | |
| 324 | |
| 325 bool LayoutThemeDefault::paintTextField(LayoutObject* o, const PaintInfo& i, con
st IntRect& rect) | |
| 326 { | |
| 327 // WebThemeEngine does not handle border rounded corner and background image | |
| 328 // so return true to draw CSS border and background. | |
| 329 if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage()) | |
| 330 return true; | |
| 331 | |
| 332 ControlPart part = o->style()->appearance(); | |
| 333 | |
| 334 WebThemeEngine::ExtraParams extraParams; | |
| 335 extraParams.textField.isTextArea = part == TextAreaPart; | |
| 336 extraParams.textField.isListbox = part == ListboxPart; | |
| 337 | |
| 338 WebCanvas* canvas = i.context->canvas(); | |
| 339 | |
| 340 Color backgroundColor = o->resolveColor(CSSPropertyBackgroundColor); | |
| 341 extraParams.textField.backgroundColor = backgroundColor.rgb(); | |
| 342 | |
| 343 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartTextFi
eld, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 344 return false; | |
| 345 } | |
| 346 | |
| 347 bool LayoutThemeDefault::paintMenuList(LayoutObject* o, const PaintInfo& i, cons
t IntRect& rect) | |
| 348 { | |
| 349 if (!o->isBox()) | |
| 350 return false; | |
| 351 | |
| 352 const int right = rect.x() + rect.width(); | |
| 353 const int middle = rect.y() + rect.height() / 2; | |
| 354 | |
| 355 WebThemeEngine::ExtraParams extraParams; | |
| 356 extraParams.menuList.arrowY = middle; | |
| 357 const LayoutBox* box = toLayoutBox(o); | |
| 358 // Match Chromium Win behaviour of showing all borders if any are shown. | |
| 359 extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() ||
box->borderTop() || box->borderBottom(); | |
| 360 extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius(); | |
| 361 // Fallback to transparent if the specified color object is invalid. | |
| 362 Color backgroundColor(Color::transparent); | |
| 363 if (o->hasBackground()) | |
| 364 backgroundColor = o->resolveColor(CSSPropertyBackgroundColor); | |
| 365 extraParams.menuList.backgroundColor = backgroundColor.rgb(); | |
| 366 | |
| 367 // If we have a background image, don't fill the content area to expose the | |
| 368 // parent's background. Also, we shouldn't fill the content area if the | |
| 369 // alpha of the color is 0. The API of Windows GDI ignores the alpha. | |
| 370 // FIXME: the normal Aura theme doesn't care about this, so we should | |
| 371 // investigate if we really need fillContentArea. | |
| 372 extraParams.menuList.fillContentArea = !o->style()->hasBackgroundImage() &&
backgroundColor.alpha(); | |
| 373 | |
| 374 if (useMockTheme()) { | |
| 375 // The size and position of the drop-down button is different between | |
| 376 // the mock theme and the regular aura theme. | |
| 377 int spacingTop = box->borderTop() + box->paddingTop(); | |
| 378 int spacingBottom = box->borderBottom() + box->paddingBottom(); | |
| 379 int spacingRight = box->borderRight() + box->paddingRight(); | |
| 380 extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x(
) + 4 + spacingRight: right - 13 - spacingRight; | |
| 381 extraParams.menuList.arrowHeight = rect.height() - spacingBottom - spaci
ngTop; | |
| 382 } else { | |
| 383 extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x(
) + 7 : right - 13; | |
| 384 } | |
| 385 | |
| 386 WebCanvas* canvas = i.context->canvas(); | |
| 387 | |
| 388 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartMenuLi
st, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 389 return false; | |
| 390 } | |
| 391 | |
| 392 bool LayoutThemeDefault::paintMenuListButton(LayoutObject* o, const PaintInfo& i
, const IntRect& rect) | |
| 393 { | |
| 394 if (!o->isBox()) | |
| 395 return false; | |
| 396 | |
| 397 const int right = rect.x() + rect.width(); | |
| 398 const int middle = rect.y() + rect.height() / 2; | |
| 399 | |
| 400 WebThemeEngine::ExtraParams extraParams; | |
| 401 extraParams.menuList.arrowY = middle; | |
| 402 extraParams.menuList.hasBorder = false; | |
| 403 extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius(); | |
| 404 extraParams.menuList.backgroundColor = Color::transparent; | |
| 405 extraParams.menuList.fillContentArea = false; | |
| 406 | |
| 407 if (useMockTheme()) { | |
| 408 const LayoutBox* box = toLayoutBox(o); | |
| 409 // The size and position of the drop-down button is different between | |
| 410 // the mock theme and the regular aura theme. | |
| 411 int spacingTop = box->borderTop() + box->paddingTop(); | |
| 412 int spacingBottom = box->borderBottom() + box->paddingBottom(); | |
| 413 int spacingRight = box->borderRight() + box->paddingRight(); | |
| 414 extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x(
) + 4 + spacingRight: right - 13 - spacingRight; | |
| 415 extraParams.menuList.arrowHeight = rect.height() - spacingBottom - spaci
ngTop; | |
| 416 } else { | |
| 417 extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x(
) + 7 : right - 13; | |
| 418 } | |
| 419 | |
| 420 WebCanvas* canvas = i.context->canvas(); | |
| 421 | |
| 422 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartMenuLi
st, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 423 return false; | |
| 424 } | |
| 425 | |
| 426 bool LayoutThemeDefault::paintSliderTrack(LayoutObject* o, const PaintInfo& i, c
onst IntRect& rect) | |
| 427 { | |
| 428 WebThemeEngine::ExtraParams extraParams; | |
| 429 WebCanvas* canvas = i.context->canvas(); | |
| 430 extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart
; | |
| 431 | |
| 432 paintSliderTicks(o, i, rect); | |
| 433 | |
| 434 // FIXME: Mock theme doesn't handle zoomed sliders. | |
| 435 float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom(); | |
| 436 GraphicsContextStateSaver stateSaver(*i.context, false); | |
| 437 IntRect unzoomedRect = rect; | |
| 438 if (zoomLevel != 1) { | |
| 439 stateSaver.save(); | |
| 440 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); | |
| 441 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); | |
| 442 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); | |
| 443 i.context->scale(zoomLevel, zoomLevel); | |
| 444 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); | |
| 445 } | |
| 446 | |
| 447 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartSlider
Track, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams); | |
| 448 | |
| 449 return false; | |
| 450 } | |
| 451 | |
| 452 bool LayoutThemeDefault::paintSliderThumb(LayoutObject* o, const PaintInfo& i, c
onst IntRect& rect) | |
| 453 { | |
| 454 WebThemeEngine::ExtraParams extraParams; | |
| 455 WebCanvas* canvas = i.context->canvas(); | |
| 456 extraParams.slider.vertical = o->style()->appearance() == SliderThumbVertica
lPart; | |
| 457 extraParams.slider.inDrag = isPressed(o); | |
| 458 | |
| 459 // FIXME: Mock theme doesn't handle zoomed sliders. | |
| 460 float zoomLevel = useMockTheme() ? 1 : o->style()->effectiveZoom(); | |
| 461 GraphicsContextStateSaver stateSaver(*i.context, false); | |
| 462 IntRect unzoomedRect = rect; | |
| 463 if (zoomLevel != 1) { | |
| 464 stateSaver.save(); | |
| 465 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); | |
| 466 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); | |
| 467 i.context->translate(unzoomedRect.x(), unzoomedRect.y()); | |
| 468 i.context->scale(zoomLevel, zoomLevel); | |
| 469 i.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); | |
| 470 } | |
| 471 | |
| 472 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartSlider
Thumb, getWebThemeState(this, o), WebRect(unzoomedRect), &extraParams); | |
| 473 return false; | |
| 474 } | |
| 475 | |
| 476 void LayoutThemeDefault::adjustInnerSpinButtonStyle(ComputedStyle& style, Elemen
t*) const | 256 void LayoutThemeDefault::adjustInnerSpinButtonStyle(ComputedStyle& style, Elemen
t*) const |
| 477 { | 257 { |
| 478 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artInnerSpinButton); | 258 IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::P
artInnerSpinButton); |
| 479 | 259 |
| 480 style.setWidth(Length(size.width(), Fixed)); | 260 style.setWidth(Length(size.width(), Fixed)); |
| 481 style.setMinWidth(Length(size.width(), Fixed)); | 261 style.setMinWidth(Length(size.width(), Fixed)); |
| 482 } | 262 } |
| 483 | 263 |
| 484 bool LayoutThemeDefault::paintInnerSpinButton(LayoutObject* o, const PaintInfo&
i, const IntRect& rect) | |
| 485 { | |
| 486 WebThemeEngine::ExtraParams extraParams; | |
| 487 WebCanvas* canvas = i.context->canvas(); | |
| 488 extraParams.innerSpin.spinUp = (controlStatesForLayoutObject(o) & SpinUpCont
rolState); | |
| 489 extraParams.innerSpin.readOnly = isReadOnlyControl(o); | |
| 490 | |
| 491 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartInnerS
pinButton, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 492 return false; | |
| 493 } | |
| 494 | |
| 495 bool LayoutThemeDefault::paintProgressBar(LayoutObject* o, const PaintInfo& i, c
onst IntRect& rect) | |
| 496 { | |
| 497 if (!o->isProgress()) | |
| 498 return true; | |
| 499 | |
| 500 LayoutProgress* layoutProgress = toLayoutProgress(o); | |
| 501 IntRect valueRect = progressValueRectFor(layoutProgress, rect); | |
| 502 | |
| 503 WebThemeEngine::ExtraParams extraParams; | |
| 504 extraParams.progressBar.determinate = layoutProgress->isDeterminate(); | |
| 505 extraParams.progressBar.valueRectX = valueRect.x(); | |
| 506 extraParams.progressBar.valueRectY = valueRect.y(); | |
| 507 extraParams.progressBar.valueRectWidth = valueRect.width(); | |
| 508 extraParams.progressBar.valueRectHeight = valueRect.height(); | |
| 509 | |
| 510 DirectionFlippingScope scope(o, i, rect); | |
| 511 WebCanvas* canvas = i.context->canvas(); | |
| 512 Platform::current()->themeEngine()->paint(canvas, WebThemeEngine::PartProgre
ssBar, getWebThemeState(this, o), WebRect(rect), &extraParams); | |
| 513 return false; | |
| 514 } | |
| 515 | |
| 516 bool LayoutThemeDefault::shouldOpenPickerWithF4Key() const | 264 bool LayoutThemeDefault::shouldOpenPickerWithF4Key() const |
| 517 { | 265 { |
| 518 return true; | 266 return true; |
| 519 } | 267 } |
| 520 | 268 |
| 521 bool LayoutThemeDefault::shouldUseFallbackTheme(const ComputedStyle& style) cons
t | 269 bool LayoutThemeDefault::shouldUseFallbackTheme(const ComputedStyle& style) cons
t |
| 522 { | 270 { |
| 523 if (useMockTheme()) { | 271 if (useMockTheme()) { |
| 524 // The mock theme can't handle zoomed controls, so we fall back to the "
fallback" theme. | 272 // The mock theme can't handle zoomed controls, so we fall back to the "
fallback" theme. |
| 525 ControlPart part = style.appearance(); | 273 ControlPart part = style.appearance(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 } | 321 } |
| 574 | 322 |
| 575 void LayoutThemeDefault::adjustButtonStyle(ComputedStyle& style, Element*) const | 323 void LayoutThemeDefault::adjustButtonStyle(ComputedStyle& style, Element*) const |
| 576 { | 324 { |
| 577 if (style.appearance() == PushButtonPart) { | 325 if (style.appearance() == PushButtonPart) { |
| 578 // Ignore line-height. | 326 // Ignore line-height. |
| 579 style.setLineHeight(ComputedStyle::initialLineHeight()); | 327 style.setLineHeight(ComputedStyle::initialLineHeight()); |
| 580 } | 328 } |
| 581 } | 329 } |
| 582 | 330 |
| 583 bool LayoutThemeDefault::paintTextArea(LayoutObject* o, const PaintInfo& i, cons
t IntRect& r) | |
| 584 { | |
| 585 return paintTextField(o, i, r); | |
| 586 } | |
| 587 | |
| 588 void LayoutThemeDefault::adjustSearchFieldStyle(ComputedStyle& style, Element*)
const | 331 void LayoutThemeDefault::adjustSearchFieldStyle(ComputedStyle& style, Element*)
const |
| 589 { | 332 { |
| 590 // Ignore line-height. | 333 // Ignore line-height. |
| 591 style.setLineHeight(ComputedStyle::initialLineHeight()); | 334 style.setLineHeight(ComputedStyle::initialLineHeight()); |
| 592 } | 335 } |
| 593 | 336 |
| 594 bool LayoutThemeDefault::paintSearchField(LayoutObject* o, const PaintInfo& i, c
onst IntRect& r) | |
| 595 { | |
| 596 return paintTextField(o, i, r); | |
| 597 } | |
| 598 | |
| 599 void LayoutThemeDefault::adjustSearchFieldCancelButtonStyle(ComputedStyle& style
, Element*) const | 337 void LayoutThemeDefault::adjustSearchFieldCancelButtonStyle(ComputedStyle& style
, Element*) const |
| 600 { | 338 { |
| 601 // Scale the button size based on the font size | 339 // Scale the button size based on the font size |
| 602 float fontScale = style.fontSize() / defaultControlFontPixelSize; | 340 float fontScale = style.fontSize() / defaultControlFontPixelSize; |
| 603 int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaul
tCancelButtonSize * fontScale), maxCancelButtonSize)); | 341 int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaul
tCancelButtonSize * fontScale), maxCancelButtonSize)); |
| 604 style.setWidth(Length(cancelButtonSize, Fixed)); | 342 style.setWidth(Length(cancelButtonSize, Fixed)); |
| 605 style.setHeight(Length(cancelButtonSize, Fixed)); | 343 style.setHeight(Length(cancelButtonSize, Fixed)); |
| 606 } | 344 } |
| 607 | 345 |
| 608 IntRect LayoutThemeDefault::convertToPaintingRect(LayoutObject* inputLayoutObjec
t, const LayoutObject* partLayoutObject, LayoutRect partRect, const IntRect& loc
alOffset) const | |
| 609 { | |
| 610 // Compute an offset between the part layoutObject and the input layoutObjec
t. | |
| 611 LayoutSize offsetFromInputLayoutObject = -partLayoutObject->offsetFromAncest
orContainer(inputLayoutObject); | |
| 612 // Move the rect into partLayoutObject's coords. | |
| 613 partRect.move(offsetFromInputLayoutObject); | |
| 614 // Account for the local drawing offset. | |
| 615 partRect.move(localOffset.x(), localOffset.y()); | |
| 616 | |
| 617 return pixelSnappedIntRect(partRect); | |
| 618 } | |
| 619 | |
| 620 bool LayoutThemeDefault::paintSearchFieldCancelButton(LayoutObject* cancelButton
Object, const PaintInfo& paintInfo, const IntRect& r) | |
| 621 { | |
| 622 // Get the layoutObject of <input> element. | |
| 623 if (!cancelButtonObject->node()) | |
| 624 return false; | |
| 625 Node* input = cancelButtonObject->node()->shadowHost(); | |
| 626 LayoutObject* baseLayoutObject = input ? input->layoutObject() : cancelButto
nObject; | |
| 627 if (!baseLayoutObject->isBox()) | |
| 628 return false; | |
| 629 LayoutBox* inputLayoutBox = toLayoutBox(baseLayoutObject); | |
| 630 LayoutRect inputContentBox = inputLayoutBox->contentBoxRect(); | |
| 631 | |
| 632 // Make sure the scaled button stays square and will fit in its parent's box
. | |
| 633 LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<Lay
outUnit>(inputContentBox.height(), r.height())); | |
| 634 // Calculate cancel button's coordinates relative to the input element. | |
| 635 // Center the button vertically. Round up though, so if it has to be one pi
xel off-center, it will | |
| 636 // be one pixel closer to the bottom of the field. This tends to look bette
r with the text. | |
| 637 LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(
inputLayoutBox).width(), | |
| 638 inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1)
/ 2, | |
| 639 cancelButtonSize, cancelButtonSize); | |
| 640 IntRect paintingRect = convertToPaintingRect(inputLayoutBox, cancelButtonObj
ect, cancelButtonRect, r); | |
| 641 | |
| 642 DEFINE_STATIC_REF(Image, cancelImage, (Image::loadPlatformResource("searchCa
ncel"))); | |
| 643 DEFINE_STATIC_REF(Image, cancelPressedImage, (Image::loadPlatformResource("s
earchCancelPressed"))); | |
| 644 paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedIm
age : cancelImage, paintingRect); | |
| 645 return false; | |
| 646 } | |
| 647 | |
| 648 void LayoutThemeDefault::adjustSearchFieldDecorationStyle(ComputedStyle& style,
Element*) const | 346 void LayoutThemeDefault::adjustSearchFieldDecorationStyle(ComputedStyle& style,
Element*) const |
| 649 { | 347 { |
| 650 IntSize emptySize(1, 11); | 348 IntSize emptySize(1, 11); |
| 651 style.setWidth(Length(emptySize.width(), Fixed)); | 349 style.setWidth(Length(emptySize.width(), Fixed)); |
| 652 style.setHeight(Length(emptySize.height(), Fixed)); | 350 style.setHeight(Length(emptySize.height(), Fixed)); |
| 653 } | 351 } |
| 654 | 352 |
| 655 void LayoutThemeDefault::adjustSearchFieldResultsDecorationStyle(ComputedStyle&
style, Element*) const | 353 void LayoutThemeDefault::adjustSearchFieldResultsDecorationStyle(ComputedStyle&
style, Element*) const |
| 656 { | 354 { |
| 657 // Scale the decoration size based on the font size | 355 // Scale the decoration size based on the font size |
| 658 float fontScale = style.fontSize() / defaultControlFontPixelSize; | 356 float fontScale = style.fontSize() / defaultControlFontPixelSize; |
| 659 int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecoratio
nSize, defaultSearchFieldResultsDecorationSize * fontScale), | 357 int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecoratio
nSize, defaultSearchFieldResultsDecorationSize * fontScale), |
| 660 maxSearchFieldResultsDecorationSize)); | 358 maxSearchFieldResultsDecorationSize)); |
| 661 style.setWidth(Length(magnifierSize, Fixed)); | 359 style.setWidth(Length(magnifierSize, Fixed)); |
| 662 style.setHeight(Length(magnifierSize, Fixed)); | 360 style.setHeight(Length(magnifierSize, Fixed)); |
| 663 } | 361 } |
| 664 | 362 |
| 665 bool LayoutThemeDefault::paintSearchFieldResultsDecoration(LayoutObject* magnifi
erObject, const PaintInfo& paintInfo, const IntRect& r) | |
| 666 { | |
| 667 // Get the layoutObject of <input> element. | |
| 668 if (!magnifierObject->node()) | |
| 669 return false; | |
| 670 Node* input = magnifierObject->node()->shadowHost(); | |
| 671 LayoutObject* baseLayoutObject = input ? input->layoutObject() : magnifierOb
ject; | |
| 672 if (!baseLayoutObject->isBox()) | |
| 673 return false; | |
| 674 LayoutBox* inputLayoutBox = toLayoutBox(baseLayoutObject); | |
| 675 LayoutRect inputContentBox = inputLayoutBox->contentBoxRect(); | |
| 676 | |
| 677 // Make sure the scaled decoration stays square and will fit in its parent's
box. | |
| 678 LayoutUnit magnifierSize = std::min(inputContentBox.width(), std::min<Layout
Unit>(inputContentBox.height(), r.height())); | |
| 679 // Calculate decoration's coordinates relative to the input element. | |
| 680 // Center the decoration vertically. Round up though, so if it has to be on
e pixel off-center, it will | |
| 681 // be one pixel closer to the bottom of the field. This tends to look bette
r with the text. | |
| 682 LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputL
ayoutBox).width(), | |
| 683 inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2
, | |
| 684 magnifierSize, magnifierSize); | |
| 685 IntRect paintingRect = convertToPaintingRect(inputLayoutBox, magnifierObject
, magnifierRect, r); | |
| 686 | |
| 687 DEFINE_STATIC_REF(Image, magnifierImage, (Image::loadPlatformResource("searc
hMagnifier"))); | |
| 688 paintInfo.context->drawImage(magnifierImage, paintingRect); | |
| 689 return false; | |
| 690 } | |
| 691 | |
| 692 bool LayoutThemeDefault::paintMediaSliderTrack(LayoutObject* object, const Paint
Info& paintInfo, const IntRect& rect) | |
| 693 { | |
| 694 return LayoutMediaControls::paintMediaControlsPart(MediaSlider, object, pain
tInfo, rect); | |
| 695 } | |
| 696 | |
| 697 bool LayoutThemeDefault::paintMediaVolumeSliderTrack(LayoutObject* object, const
PaintInfo& paintInfo, const IntRect& rect) | |
| 698 { | |
| 699 return LayoutMediaControls::paintMediaControlsPart(MediaVolumeSlider, object
, paintInfo, rect); | |
| 700 } | |
| 701 | |
| 702 bool LayoutThemeDefault::paintMediaSliderThumb(LayoutObject* object, const Paint
Info& paintInfo, const IntRect& rect) | |
| 703 { | |
| 704 return LayoutMediaControls::paintMediaControlsPart(MediaSliderThumb, object,
paintInfo, rect); | |
| 705 } | |
| 706 | |
| 707 bool LayoutThemeDefault::paintMediaToggleClosedCaptionsButton(LayoutObject* o, c
onst PaintInfo& paintInfo, const IntRect& r) | |
| 708 { | |
| 709 return LayoutMediaControls::paintMediaControlsPart(MediaShowClosedCaptionsBu
tton, o, paintInfo, r); | |
| 710 } | |
| 711 | |
| 712 bool LayoutThemeDefault::paintMediaCastButton(LayoutObject* o, const PaintInfo&
paintInfo, const IntRect& r) | |
| 713 { | |
| 714 return LayoutMediaControls::paintMediaControlsPart(MediaCastOffButton, o, pa
intInfo, r); | |
| 715 } | |
| 716 | |
| 717 bool LayoutThemeDefault::paintMediaVolumeSliderThumb(LayoutObject* object, const
PaintInfo& paintInfo, const IntRect& rect) | |
| 718 { | |
| 719 return LayoutMediaControls::paintMediaControlsPart(MediaVolumeSliderThumb, o
bject, paintInfo, rect); | |
| 720 } | |
| 721 | |
| 722 bool LayoutThemeDefault::paintMediaPlayButton(LayoutObject* object, const PaintI
nfo& paintInfo, const IntRect& rect) | |
| 723 { | |
| 724 return LayoutMediaControls::paintMediaControlsPart(MediaPlayButton, object,
paintInfo, rect); | |
| 725 } | |
| 726 | |
| 727 bool LayoutThemeDefault::paintMediaOverlayPlayButton(LayoutObject* object, const
PaintInfo& paintInfo, const IntRect& rect) | |
| 728 { | |
| 729 return LayoutMediaControls::paintMediaControlsPart(MediaOverlayPlayButton, o
bject, paintInfo, rect); | |
| 730 } | |
| 731 | |
| 732 bool LayoutThemeDefault::paintMediaMuteButton(LayoutObject* object, const PaintI
nfo& paintInfo, const IntRect& rect) | |
| 733 { | |
| 734 return LayoutMediaControls::paintMediaControlsPart(MediaMuteButton, object,
paintInfo, rect); | |
| 735 } | |
| 736 | |
| 737 String LayoutThemeDefault::formatMediaControlsTime(float time) const | |
| 738 { | |
| 739 return LayoutMediaControls::formatMediaControlsTime(time); | |
| 740 } | |
| 741 | |
| 742 String LayoutThemeDefault::formatMediaControlsCurrentTime(float currentTime, flo
at duration) const | |
| 743 { | |
| 744 return LayoutMediaControls::formatMediaControlsCurrentTime(currentTime, dura
tion); | |
| 745 } | |
| 746 | |
| 747 bool LayoutThemeDefault::paintMediaFullscreenButton(LayoutObject* object, const
PaintInfo& paintInfo, const IntRect& rect) | |
| 748 { | |
| 749 return LayoutMediaControls::paintMediaControlsPart(MediaEnterFullscreenButto
n, object, paintInfo, rect); | |
| 750 } | |
| 751 | |
| 752 void LayoutThemeDefault::adjustMenuListStyle(ComputedStyle& style, Element*) con
st | 363 void LayoutThemeDefault::adjustMenuListStyle(ComputedStyle& style, Element*) con
st |
| 753 { | 364 { |
| 754 // Height is locked to auto on all browsers. | 365 // Height is locked to auto on all browsers. |
| 755 style.setLineHeight(ComputedStyle::initialLineHeight()); | 366 style.setLineHeight(ComputedStyle::initialLineHeight()); |
| 756 } | 367 } |
| 757 | 368 |
| 758 void LayoutThemeDefault::adjustMenuListButtonStyle(ComputedStyle& style, Element
* e) const | 369 void LayoutThemeDefault::adjustMenuListButtonStyle(ComputedStyle& style, Element
* e) const |
| 759 { | 370 { |
| 760 adjustMenuListStyle(style, e); | 371 adjustMenuListStyle(style, e); |
| 761 } | 372 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 } | 421 } |
| 811 | 422 |
| 812 bool LayoutThemeDefault::shouldShowPlaceholderWhenFocused() const | 423 bool LayoutThemeDefault::shouldShowPlaceholderWhenFocused() const |
| 813 { | 424 { |
| 814 return true; | 425 return true; |
| 815 } | 426 } |
| 816 | 427 |
| 817 // | 428 // |
| 818 // Following values are come from default of GTK+ | 429 // Following values are come from default of GTK+ |
| 819 // | 430 // |
| 820 static const int progressActivityBlocks = 5; | |
| 821 static const int progressAnimationFrames = 10; | 431 static const int progressAnimationFrames = 10; |
| 822 static const double progressAnimationInterval = 0.125; | 432 static const double progressAnimationInterval = 0.125; |
| 823 | 433 |
| 824 IntRect LayoutThemeDefault::determinateProgressValueRectFor(LayoutProgress* layo
utProgress, const IntRect& rect) const | |
| 825 { | |
| 826 int dx = rect.width() * layoutProgress->position(); | |
| 827 return IntRect(rect.x(), rect.y(), dx, rect.height()); | |
| 828 } | |
| 829 | |
| 830 IntRect LayoutThemeDefault::indeterminateProgressValueRectFor(LayoutProgress* la
youtProgress, const IntRect& rect) const | |
| 831 { | |
| 832 | |
| 833 int valueWidth = rect.width() / progressActivityBlocks; | |
| 834 int movableWidth = rect.width() - valueWidth; | |
| 835 if (movableWidth <= 0) | |
| 836 return IntRect(); | |
| 837 | |
| 838 double progress = layoutProgress->animationProgress(); | |
| 839 if (progress < 0.5) | |
| 840 return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWi
dth, rect.height()); | |
| 841 return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), val
ueWidth, rect.height()); | |
| 842 } | |
| 843 | |
| 844 double LayoutThemeDefault::animationRepeatIntervalForProgressBar() const | 434 double LayoutThemeDefault::animationRepeatIntervalForProgressBar() const |
| 845 { | 435 { |
| 846 return progressAnimationInterval; | 436 return progressAnimationInterval; |
| 847 } | 437 } |
| 848 | 438 |
| 849 double LayoutThemeDefault::animationDurationForProgressBar() const | 439 double LayoutThemeDefault::animationDurationForProgressBar() const |
| 850 { | 440 { |
| 851 return progressAnimationInterval * progressAnimationFrames * 2; // "2" for b
ack and forth | 441 return progressAnimationInterval * progressAnimationFrames * 2; // "2" for b
ack and forth |
| 852 } | 442 } |
| 853 | 443 |
| 854 IntRect LayoutThemeDefault::progressValueRectFor(LayoutProgress* layoutProgress,
const IntRect& rect) const | |
| 855 { | |
| 856 return layoutProgress->isDeterminate() ? determinateProgressValueRectFor(lay
outProgress, rect) : indeterminateProgressValueRectFor(layoutProgress, rect); | |
| 857 } | |
| 858 | |
| 859 LayoutThemeDefault::DirectionFlippingScope::DirectionFlippingScope(LayoutObject*
layoutObject, const PaintInfo& paintInfo, const IntRect& rect) | |
| 860 : m_needsFlipping(!layoutObject->style()->isLeftToRightDirection()) | |
| 861 , m_paintInfo(paintInfo) | |
| 862 { | |
| 863 if (!m_needsFlipping) | |
| 864 return; | |
| 865 m_paintInfo.context->save(); | |
| 866 m_paintInfo.context->translate(2 * rect.x() + rect.width(), 0); | |
| 867 m_paintInfo.context->scale(-1, 1); | |
| 868 } | |
| 869 | |
| 870 LayoutThemeDefault::DirectionFlippingScope::~DirectionFlippingScope() | |
| 871 { | |
| 872 if (!m_needsFlipping) | |
| 873 return; | |
| 874 m_paintInfo.context->restore(); | |
| 875 } | |
| 876 | |
| 877 } // namespace blink | 444 } // namespace blink |
| OLD | NEW |