1/* 2 * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. 3 * Copyright (C) 2009 Kenneth Rohde Christiansen 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 * 20 */ 21 22#include "config.h" 23#include "RenderThemeSafari.h" 24#include "RenderThemeWin.h" 25#include "Settings.h" 26 27#if USE(SAFARI_THEME) 28 29#include "CSSFontSelector.h" 30#include "CSSValueKeywords.h" 31#include "Document.h" 32#include "Element.h" 33#include "Frame.h" 34#include "FrameView.h" 35#include "GraphicsContextCG.h" 36#include "HTMLInputElement.h" 37#include "HTMLMediaElement.h" 38#include "HTMLMeterElement.h" 39#include "HTMLNames.h" 40#include "PaintInfo.h" 41#include "RenderMediaControls.h" 42#include "RenderMeter.h" 43#include "RenderSlider.h" 44#include "RenderView.h" 45#include "SoftLinking.h" 46#include "StyleResolver.h" 47#include <CoreGraphics/CoreGraphics.h> 48#include <wtf/RetainPtr.h> 49 50using std::min; 51 52// FIXME: The platform-independent code in this class should be factored out and merged with RenderThemeMac. 53 54namespace WebCore { 55 56using namespace HTMLNames; 57using namespace SafariTheme; 58 59enum { 60 topMargin, 61 rightMargin, 62 bottomMargin, 63 leftMargin 64}; 65 66enum { 67 topPadding, 68 rightPadding, 69 bottomPadding, 70 leftPadding 71}; 72 73PassRefPtr<RenderTheme> RenderThemeSafari::create() 74{ 75 return adoptRef(new RenderThemeSafari); 76} 77 78PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) 79{ 80 static RenderTheme* safariTheme = RenderThemeSafari::create().leakRef(); 81 static RenderTheme* windowsTheme = RenderThemeWin::create().leakRef(); 82 83 // FIXME: This is called before Settings has been initialized by WebKit, so will return a 84 // potentially wrong answer the very first time it's called (see 85 // <https://bugs.webkit.org/show_bug.cgi?id=26493>). 86 if (Settings::shouldPaintNativeControls()) { 87 RenderTheme::setCustomFocusRingColor(safariTheme->platformFocusRingColor()); 88 return windowsTheme; // keep the reference of one. 89 } 90 return safariTheme; // keep the reference of one. 91} 92 93#ifdef DEBUG_ALL 94SOFT_LINK_DEBUG_LIBRARY(SafariTheme) 95#else 96SOFT_LINK_LIBRARY(SafariTheme) 97#endif 98 99SOFT_LINK(SafariTheme, paintThemePart, void, __stdcall, (ThemePart part, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state), (part, context, rect, size, state)) 100#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 2 101SOFT_LINK(SafariTheme, STPaintProgressIndicator, void, APIENTRY, (ProgressIndicatorType type, CGContextRef context, const CGRect& rect, NSControlSize size, ThemeControlState state, float value), (type, context, rect, size, state, value)) 102#endif 103SOFT_LINK_OPTIONAL(SafariTheme, STCopyThemeColor, CGColorRef, APIENTRY, (unsigned color, SafariTheme::ThemeControlState)); 104 105static const unsigned stFocusRingColorID = 4; 106 107static const unsigned aquaFocusRingColor = 0xFF7DADD9; 108 109static RGBA32 makeRGBAFromCGColor(CGColorRef color) 110{ 111 const CGFloat* components = CGColorGetComponents(color); 112 return makeRGBA(255 * components[0], 255 * components[1], 255 * components[2], 255 * components[3]); 113} 114 115ThemeControlState RenderThemeSafari::determineState(RenderObject* o) const 116{ 117 ThemeControlState result = 0; 118 if (isActive(o)) 119 result |= SafariTheme::ActiveState; 120 if (isEnabled(o) && !isReadOnlyControl(o)) 121 result |= SafariTheme::EnabledState; 122 if (isPressed(o)) 123 result |= SafariTheme::PressedState; 124 if (isChecked(o)) 125 result |= SafariTheme::CheckedState; 126 if (isIndeterminate(o)) 127 result |= SafariTheme::IndeterminateCheckedState; 128 if (isFocused(o)) 129 result |= SafariTheme::FocusedState; 130 if (isDefault(o)) 131 result |= SafariTheme::DefaultState; 132 return result; 133} 134 135static NSControlSize controlSizeFromRect(const IntRect& rect, const IntSize sizes[]) 136{ 137 if (sizes[NSRegularControlSize].height() == rect.height()) 138 return NSRegularControlSize; 139 else if (sizes[NSMiniControlSize].height() == rect.height()) 140 return NSMiniControlSize; 141 142 return NSSmallControlSize; 143} 144 145RenderThemeSafari::RenderThemeSafari() 146{ 147} 148 149RenderThemeSafari::~RenderThemeSafari() 150{ 151} 152 153Color RenderThemeSafari::platformActiveSelectionBackgroundColor() const 154{ 155 return Color(181, 213, 255); 156} 157 158Color RenderThemeSafari::platformInactiveSelectionBackgroundColor() const 159{ 160 return Color(212, 212, 212); 161} 162 163Color RenderThemeSafari::activeListBoxSelectionBackgroundColor() const 164{ 165 // FIXME: This should probably just be a darker version of the platformActiveSelectionBackgroundColor 166 return Color(56, 117, 215); 167} 168 169Color RenderThemeSafari::platformFocusRingColor() const 170{ 171 static Color focusRingColor; 172 173 if (!focusRingColor.isValid()) { 174 if (STCopyThemeColorPtr()) { 175 RetainPtr<CGColorRef> color = adoptCF(STCopyThemeColorPtr()(stFocusRingColorID, SafariTheme::ActiveState)); 176 focusRingColor = makeRGBAFromCGColor(color.get()); 177 } 178 if (!focusRingColor.isValid()) 179 focusRingColor = aquaFocusRingColor; 180 } 181 182 return focusRingColor; 183} 184 185static float systemFontSizeForControlSize(NSControlSize controlSize) 186{ 187 static float sizes[] = { 13.0f, 11.0f, 9.0f }; 188 189 return sizes[controlSize]; 190} 191 192void RenderThemeSafari::systemFont(int propId, FontDescription& fontDescription) const 193{ 194 static FontDescription systemFont; 195 static FontDescription smallSystemFont; 196 static FontDescription menuFont; 197 static FontDescription labelFont; 198 static FontDescription miniControlFont; 199 static FontDescription smallControlFont; 200 static FontDescription controlFont; 201 202 FontDescription* cachedDesc; 203 float fontSize = 0; 204 switch (propId) { 205 case CSSValueSmallCaption: 206 cachedDesc = &smallSystemFont; 207 if (!smallSystemFont.isAbsoluteSize()) 208 fontSize = systemFontSizeForControlSize(NSSmallControlSize); 209 break; 210 case CSSValueMenu: 211 cachedDesc = &menuFont; 212 if (!menuFont.isAbsoluteSize()) 213 fontSize = systemFontSizeForControlSize(NSRegularControlSize); 214 break; 215 case CSSValueStatusBar: 216 cachedDesc = &labelFont; 217 if (!labelFont.isAbsoluteSize()) 218 fontSize = 10.0f; 219 break; 220 case CSSValueWebkitMiniControl: 221 cachedDesc = &miniControlFont; 222 if (!miniControlFont.isAbsoluteSize()) 223 fontSize = systemFontSizeForControlSize(NSMiniControlSize); 224 break; 225 case CSSValueWebkitSmallControl: 226 cachedDesc = &smallControlFont; 227 if (!smallControlFont.isAbsoluteSize()) 228 fontSize = systemFontSizeForControlSize(NSSmallControlSize); 229 break; 230 case CSSValueWebkitControl: 231 cachedDesc = &controlFont; 232 if (!controlFont.isAbsoluteSize()) 233 fontSize = systemFontSizeForControlSize(NSRegularControlSize); 234 break; 235 default: 236 cachedDesc = &systemFont; 237 if (!systemFont.isAbsoluteSize()) 238 fontSize = 13.0f; 239 } 240 241 if (fontSize) { 242 cachedDesc->setIsAbsoluteSize(true); 243 cachedDesc->setGenericFamily(FontDescription::NoFamily); 244 cachedDesc->setOneFamily("Lucida Grande"); 245 cachedDesc->setSpecifiedSize(fontSize); 246 cachedDesc->setWeight(FontWeightNormal); 247 cachedDesc->setItalic(false); 248 } 249 fontDescription = *cachedDesc; 250} 251 252bool RenderThemeSafari::isControlStyled(const RenderStyle* style, const BorderData& border, 253 const FillLayer& background, const Color& backgroundColor) const 254{ 255 // If we didn't find SafariTheme.dll we won't be able to paint any themed controls. 256 if (!SafariThemeLibrary()) 257 return true; 258 259 if (style->appearance() == TextFieldPart || style->appearance() == TextAreaPart || style->appearance() == ListboxPart) 260 return style->border() != border; 261 return RenderTheme::isControlStyled(style, border, background, backgroundColor); 262} 263 264void RenderThemeSafari::adjustRepaintRect(const RenderObject* o, IntRect& r) 265{ 266 NSControlSize controlSize = controlSizeForFont(o->style()); 267 268 switch (o->style()->appearance()) { 269 case CheckboxPart: { 270 // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox 271 // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. 272 r = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize)); 273 break; 274 } 275 case RadioPart: { 276 // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox 277 // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. 278 r = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize)); 279 break; 280 } 281 case PushButtonPart: 282 case DefaultButtonPart: 283 case ButtonPart: { 284 // We inflate the rect as needed to account for padding included in the cell to accommodate the checkbox 285 // shadow" and the check. We don't consider this part of the bounds of the control in WebKit. 286 if (r.height() <= buttonSizes()[NSRegularControlSize].height()) 287 r = inflateRect(r, buttonSizes()[controlSize], buttonMargins(controlSize)); 288 break; 289 } 290 case MenulistPart: { 291 r = inflateRect(r, popupButtonSizes()[controlSize], popupButtonMargins(controlSize)); 292 break; 293 } 294 default: 295 break; 296 } 297} 298 299IntRect RenderThemeSafari::inflateRect(const IntRect& r, const IntSize& size, const int* margins) const 300{ 301 // Only do the inflation if the available width/height are too small. Otherwise try to 302 // fit the glow/check space into the available box's width/height. 303 int widthDelta = r.width() - (size.width() + margins[leftMargin] + margins[rightMargin]); 304 int heightDelta = r.height() - (size.height() + margins[topMargin] + margins[bottomMargin]); 305 IntRect result(r); 306 if (widthDelta < 0) { 307 result.setX(result.x() - margins[leftMargin]); 308 result.setWidth(result.width() - widthDelta); 309 } 310 if (heightDelta < 0) { 311 result.setY(result.y() - margins[topMargin]); 312 result.setHeight(result.height() - heightDelta); 313 } 314 return result; 315} 316 317int RenderThemeSafari::baselinePosition(const RenderObject* o) const 318{ 319 if (!o->isBox()) 320 return 0; 321 322 if (o->style()->appearance() == CheckboxPart || o->style()->appearance() == RadioPart) { 323 const RenderBox* box = toRenderBox(o); 324 return box->marginTop() + box->height() - 2; // The baseline is 2px up from the bottom of the checkbox/radio in AppKit. 325 } 326 327 return RenderTheme::baselinePosition(o); 328} 329 330bool RenderThemeSafari::controlSupportsTints(const RenderObject* o) const 331{ 332 if (!isEnabled(o)) 333 return false; 334 335 // Checkboxes only have tint when checked. 336 if (o->style()->appearance() == CheckboxPart) 337 return isChecked(o); 338 339 // For now assume other controls have tint if enabled. 340 return true; 341} 342 343NSControlSize RenderThemeSafari::controlSizeForFont(RenderStyle* style) const 344{ 345 int fontSize = style->fontSize(); 346 if (fontSize >= 16) 347 return NSRegularControlSize; 348 if (fontSize >= 11) 349 return NSSmallControlSize; 350 return NSMiniControlSize; 351} 352/* 353void RenderThemeSafari::setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minSize) 354{ 355 NSControlSize size; 356 if (minSize.width() >= sizes[NSRegularControlSize].width() && 357 minSize.height() >= sizes[NSRegularControlSize].height()) 358 size = NSRegularControlSize; 359 else if (minSize.width() >= sizes[NSSmallControlSize].width() && 360 minSize.height() >= sizes[NSSmallControlSize].height()) 361 size = NSSmallControlSize; 362 else 363 size = NSMiniControlSize; 364 if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same. 365 [cell setControlSize:size]; 366} 367*/ 368IntSize RenderThemeSafari::sizeForFont(RenderStyle* style, const IntSize* sizes) const 369{ 370 return sizes[controlSizeForFont(style)]; 371} 372 373IntSize RenderThemeSafari::sizeForSystemFont(RenderStyle* style, const IntSize* sizes) const 374{ 375 return sizes[controlSizeForSystemFont(style)]; 376} 377 378void RenderThemeSafari::setSizeFromFont(RenderStyle* style, const IntSize* sizes) const 379{ 380 // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. 381 IntSize size = sizeForFont(style, sizes); 382 if (style->width().isIntrinsicOrAuto() && size.width() > 0) 383 style->setWidth(Length(size.width(), Fixed)); 384 if (style->height().isAuto() && size.height() > 0) 385 style->setHeight(Length(size.height(), Fixed)); 386} 387 388void RenderThemeSafari::setFontFromControlSize(StyleResolver* styleResolver, RenderStyle* style, NSControlSize controlSize) const 389{ 390 FontDescription fontDescription; 391 fontDescription.setIsAbsoluteSize(true); 392 fontDescription.setGenericFamily(FontDescription::SerifFamily); 393 394 float fontSize = systemFontSizeForControlSize(controlSize); 395 fontDescription.setOneFamily("Lucida Grande"); 396 fontDescription.setComputedSize(fontSize); 397 fontDescription.setSpecifiedSize(fontSize); 398 399 // Reset line height 400 style->setLineHeight(RenderStyle::initialLineHeight()); 401 402 if (style->setFontDescription(fontDescription)) 403 style->font().update(styleResolver->fontSelector()); 404} 405 406NSControlSize RenderThemeSafari::controlSizeForSystemFont(RenderStyle* style) const 407{ 408 int fontSize = style->fontSize(); 409 if (fontSize >= 13) 410 return NSRegularControlSize; 411 if (fontSize >= 11) 412 return NSSmallControlSize; 413 return NSMiniControlSize; 414} 415 416bool RenderThemeSafari::paintCheckbox(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 417{ 418 ASSERT(SafariThemeLibrary()); 419 420 NSControlSize controlSize = controlSizeForFont(o->style()); 421 422 IntRect inflatedRect = inflateRect(r, checkboxSizes()[controlSize], checkboxMargins(controlSize)); 423 paintThemePart(SafariTheme::CheckboxPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o)); 424 425 return false; 426} 427 428const IntSize* RenderThemeSafari::checkboxSizes() const 429{ 430 static const IntSize sizes[3] = { IntSize(14, 14), IntSize(12, 12), IntSize(10, 10) }; 431 return sizes; 432} 433 434const int* RenderThemeSafari::checkboxMargins(NSControlSize controlSize) const 435{ 436 static const int margins[3][4] = 437 { 438 { 2, 2, 2, 2 }, 439 { 2, 2, 2, 1 }, 440 { 1, 0, 0, 0 }, 441 }; 442 return margins[controlSize]; 443} 444 445void RenderThemeSafari::setCheckboxSize(RenderStyle* style) const 446{ 447 // If the width and height are both specified, then we have nothing to do. 448 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 449 return; 450 451 // Use the font size to determine the intrinsic width of the control. 452 setSizeFromFont(style, checkboxSizes()); 453} 454 455bool RenderThemeSafari::paintRadio(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 456{ 457 ASSERT(SafariThemeLibrary()); 458 459 NSControlSize controlSize = controlSizeForFont(o->style()); 460 461 IntRect inflatedRect = inflateRect(r, radioSizes()[controlSize], radioMargins(controlSize)); 462 paintThemePart(RadioButtonPart, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o)); 463 464 return false; 465} 466 467const IntSize* RenderThemeSafari::radioSizes() const 468{ 469 static const IntSize sizes[3] = { IntSize(14, 15), IntSize(12, 13), IntSize(10, 10) }; 470 return sizes; 471} 472 473const int* RenderThemeSafari::radioMargins(NSControlSize controlSize) const 474{ 475 static const int margins[3][4] = 476 { 477 { 1, 2, 2, 2 }, 478 { 0, 1, 2, 1 }, 479 { 0, 0, 1, 0 }, 480 }; 481 return margins[controlSize]; 482} 483 484void RenderThemeSafari::setRadioSize(RenderStyle* style) const 485{ 486 // If the width and height are both specified, then we have nothing to do. 487 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 488 return; 489 490 // Use the font size to determine the intrinsic width of the control. 491 setSizeFromFont(style, radioSizes()); 492} 493 494void RenderThemeSafari::setButtonPaddingFromControlSize(RenderStyle* style, NSControlSize size) const 495{ 496 // Just use 8px. AppKit wants to use 11px for mini buttons, but that padding is just too large 497 // for real-world Web sites (creating a huge necessary minimum width for buttons whose space is 498 // by definition constrained, since we select mini only for small cramped environments. 499 // This also guarantees the HTML4 <button> will match our rendering by default, since we're using a consistent 500 // padding. 501 const int padding = 8; 502 style->setPaddingLeft(Length(padding, Fixed)); 503 style->setPaddingRight(Length(padding, Fixed)); 504 style->setPaddingTop(Length(0, Fixed)); 505 style->setPaddingBottom(Length(0, Fixed)); 506} 507 508void RenderThemeSafari::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const 509{ 510 // There are three appearance constants for buttons. 511 // (1) Push-button is the constant for the default Aqua system button. Push buttons will not scale vertically and will not allow 512 // custom fonts or colors. <input>s use this constant. This button will allow custom colors and font weights/variants but won't 513 // scale vertically. 514 // (2) square-button is the constant for the square button. This button will allow custom fonts and colors and will scale vertically. 515 // (3) Button is the constant that means "pick the best button as appropriate." <button>s use this constant. This button will 516 // also scale vertically and allow custom fonts and colors. It will attempt to use Aqua if possible and will make this determination 517 // solely on the rectangle of the control. 518 519 // Determine our control size based off our font. 520 NSControlSize controlSize = controlSizeForFont(style); 521 522 if (style->appearance() == PushButtonPart) { 523 // Ditch the border. 524 style->resetBorder(); 525 526 // Height is locked to auto. 527 style->setHeight(Length(Auto)); 528 529 // White-space is locked to pre 530 style->setWhiteSpace(PRE); 531 532 // Set the button's vertical size. 533 setButtonSize(style); 534 535 // Add in the padding that we'd like to use. 536 setButtonPaddingFromControlSize(style, controlSize); 537 538 // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out 539 // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate 540 // system font for the control size instead. 541 setFontFromControlSize(styleResolver, style, controlSize); 542 } else { 543 // Set a min-height so that we can't get smaller than the mini button. 544 style->setMinHeight(Length(15, Fixed)); 545 546 // Reset the top and bottom borders. 547 style->resetBorderTop(); 548 style->resetBorderBottom(); 549 } 550} 551 552const IntSize* RenderThemeSafari::buttonSizes() const 553{ 554 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 555 return sizes; 556} 557 558const int* RenderThemeSafari::buttonMargins(NSControlSize controlSize) const 559{ 560 static const int margins[3][4] = 561 { 562 { 4, 6, 7, 6 }, 563 { 4, 5, 6, 5 }, 564 { 0, 1, 1, 1 }, 565 }; 566 return margins[controlSize]; 567} 568 569void RenderThemeSafari::setButtonSize(RenderStyle* style) const 570{ 571 // If the width and height are both specified, then we have nothing to do. 572 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 573 return; 574 575 // Use the font size to determine the intrinsic width of the control. 576 setSizeFromFont(style, buttonSizes()); 577} 578 579bool RenderThemeSafari::paintButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 580{ 581 ASSERT(SafariThemeLibrary()); 582 583 // We inflate the rect as needed to account for padding included in the cell to accommodate the button 584 // shadow. We don't consider this part of the bounds of the control in WebKit. 585 586 NSControlSize controlSize = controlSizeFromRect(r, buttonSizes()); 587 IntRect inflatedRect = r; 588 589 ThemePart part; 590 if (r.height() <= buttonSizes()[NSRegularControlSize].height()) { 591 // Push button 592 part = SafariTheme::PushButtonPart; 593 594 IntSize size = buttonSizes()[controlSize]; 595 size.setWidth(r.width()); 596 597 // Center the button within the available space. 598 if (inflatedRect.height() > size.height()) { 599 inflatedRect.setY(inflatedRect.y() + (inflatedRect.height() - size.height()) / 2); 600 inflatedRect.setHeight(size.height()); 601 } 602 603 // Now inflate it to account for the shadow. 604 inflatedRect = inflateRect(inflatedRect, size, buttonMargins(controlSize)); 605 } else 606 part = SafariTheme::SquareButtonPart; 607 608 paintThemePart(part, paintInfo.context->platformContext(), inflatedRect, controlSize, determineState(o)); 609 return false; 610} 611 612bool RenderThemeSafari::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 613{ 614 ASSERT(SafariThemeLibrary()); 615 616 paintThemePart(SafariTheme::TextFieldPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState); 617 return false; 618} 619 620void RenderThemeSafari::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const 621{ 622} 623 624bool RenderThemeSafari::paintCapsLockIndicator(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 625{ 626#if defined(SAFARI_THEME_VERSION) && SAFARI_THEME_VERSION >= 1 627 ASSERT(SafariThemeLibrary()); 628 629 if (paintInfo.context->paintingDisabled()) 630 return true; 631 632 paintThemePart(CapsLockPart, paintInfo.context->platformContext(), r, (NSControlSize)0, (ThemeControlState)0); 633 634 return false; 635#else 636 return true; 637#endif 638} 639 640bool RenderThemeSafari::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 641{ 642 ASSERT(SafariThemeLibrary()); 643 644 paintThemePart(SafariTheme::TextAreaPart, paintInfo.context->platformContext(), r, (NSControlSize)0, determineState(o) & ~FocusedState); 645 return false; 646} 647 648void RenderThemeSafari::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const 649{ 650} 651 652const int* RenderThemeSafari::popupButtonMargins(NSControlSize size) const 653{ 654 static const int margins[3][4] = 655 { 656 { 2, 3, 3, 3 }, 657 { 1, 3, 3, 3 }, 658 { 0, 1, 0, 1 } 659 }; 660 return margins[size]; 661} 662 663const IntSize* RenderThemeSafari::popupButtonSizes() const 664{ 665 static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) }; 666 return sizes; 667} 668 669const int* RenderThemeSafari::popupButtonPadding(NSControlSize size) const 670{ 671 static const int padding[3][4] = 672 { 673 { 2, 26, 3, 8 }, 674 { 2, 23, 3, 8 }, 675 { 2, 22, 3, 10 } 676 }; 677 return padding[size]; 678} 679 680bool RenderThemeSafari::paintMenuList(RenderObject* o, const PaintInfo& info, const IntRect& r) 681{ 682 ASSERT(SafariThemeLibrary()); 683 684 NSControlSize controlSize = controlSizeFromRect(r, popupButtonSizes()); 685 IntRect inflatedRect = r; 686 IntSize size = popupButtonSizes()[controlSize]; 687 size.setWidth(r.width()); 688 689 // Now inflate it to account for the shadow. 690 if (r.width() >= minimumMenuListSize(o->style())) 691 inflatedRect = inflateRect(inflatedRect, size, popupButtonMargins(controlSize)); 692 693 paintThemePart(DropDownButtonPart, info.context->platformContext(), inflatedRect, controlSize, determineState(o)); 694 695 return false; 696} 697 698const float baseFontSize = 11.0f; 699const float baseArrowHeight = 5.0f; 700const float baseArrowWidth = 7.0f; 701const int arrowPaddingLeft = 5; 702const int arrowPaddingRight = 5; 703const int paddingBeforeSeparator = 4; 704const int baseBorderRadius = 5; 705const int styledPopupPaddingLeft = 8; 706const int styledPopupPaddingTop = 1; 707const int styledPopupPaddingBottom = 2; 708 709static void TopGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) 710{ 711 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.4f }; 712 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.15f }; 713 float a = inData[0]; 714 int i = 0; 715 for (i = 0; i < 4; i++) 716 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 717} 718 719static void BottomGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) 720{ 721 static float dark[4] = { 1.0f, 1.0f, 1.0f, 0.0f }; 722 static float light[4] = { 1.0f, 1.0f, 1.0f, 0.3f }; 723 float a = inData[0]; 724 int i = 0; 725 for (i = 0; i < 4; i++) 726 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 727} 728 729static void MainGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) 730{ 731 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.15f }; 732 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; 733 float a = inData[0]; 734 int i = 0; 735 for (i = 0; i < 4; i++) 736 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 737} 738 739static void TrackGradientInterpolate(void* info, const CGFloat* inData, CGFloat* outData) 740{ 741 static float dark[4] = { 0.0f, 0.0f, 0.0f, 0.678f }; 742 static float light[4] = { 0.0f, 0.0f, 0.0f, 0.13f }; 743 float a = inData[0]; 744 int i = 0; 745 for (i = 0; i < 4; i++) 746 outData[i] = (1.0f - a) * dark[i] + a * light[i]; 747} 748 749void RenderThemeSafari::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 750{ 751 if (r.isEmpty()) 752 return; 753 754 CGContextRef context = paintInfo.context->platformContext(); 755 756 paintInfo.context->save(); 757 758 RoundedRect bound = o->style()->getRoundedBorderFor(r); 759 int radius = bound.radii().topLeft().width(); 760 761 CGColorSpaceRef cspace = deviceRGBColorSpaceRef(); 762 763 FloatRect topGradient(r.x(), r.y(), r.width(), r.height() / 2.0f); 764 struct CGFunctionCallbacks topCallbacks = { 0, TopGradientInterpolate, NULL }; 765 RetainPtr<CGFunctionRef> topFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &topCallbacks)); 766 RetainPtr<CGShadingRef> topShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), topFunction.get(), false, false)); 767 768 FloatRect bottomGradient(r.x() + radius, r.y() + r.height() / 2.0f, r.width() - 2.0f * radius, r.height() / 2.0f); 769 struct CGFunctionCallbacks bottomCallbacks = { 0, BottomGradientInterpolate, NULL }; 770 RetainPtr<CGFunctionRef> bottomFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &bottomCallbacks)); 771 RetainPtr<CGShadingRef> bottomShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bottomGradient.x(), bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), bottomFunction.get(), false, false)); 772 773 struct CGFunctionCallbacks mainCallbacks = { 0, MainGradientInterpolate, NULL }; 774 RetainPtr<CGFunctionRef> mainFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); 775 RetainPtr<CGShadingRef> mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false)); 776 777 RetainPtr<CGShadingRef> leftShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.x(), r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false)); 778 779 RetainPtr<CGShadingRef> rightShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(r.maxX(), r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false)); 780 paintInfo.context->save(); 781 CGContextClipToRect(context, bound.rect()); 782 paintInfo.context->clipRoundedRect(bound); 783 CGContextDrawShading(context, mainShading.get()); 784 paintInfo.context->restore(); 785 786 paintInfo.context->save(); 787 CGContextClipToRect(context, topGradient); 788 paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(topGradient), bound.radii().topLeft(), bound.radii().topRight(), IntSize(), IntSize())); 789 CGContextDrawShading(context, topShading.get()); 790 paintInfo.context->restore(); 791 792 if (!bottomGradient.isEmpty()) { 793 paintInfo.context->save(); 794 CGContextClipToRect(context, bottomGradient); 795 paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), bound.radii().bottomLeft(), bound.radii().bottomRight())); 796 CGContextDrawShading(context, bottomShading.get()); 797 paintInfo.context->restore(); 798 } 799 800 paintInfo.context->save(); 801 CGContextClipToRect(context, bound.rect()); 802 paintInfo.context->clipRoundedRect(bound); 803 CGContextDrawShading(context, leftShading.get()); 804 CGContextDrawShading(context, rightShading.get()); 805 paintInfo.context->restore(); 806 807 paintInfo.context->restore(); 808} 809 810bool RenderThemeSafari::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 811{ 812 IntRect bounds = IntRect(r.x() + o->style()->borderLeftWidth(), 813 r.y() + o->style()->borderTopWidth(), 814 r.width() - o->style()->borderLeftWidth() - o->style()->borderRightWidth(), 815 r.height() - o->style()->borderTopWidth() - o->style()->borderBottomWidth()); 816 // Draw the gradients to give the styled popup menu a button appearance 817 paintMenuListButtonGradients(o, paintInfo, bounds); 818 819 // Since we actually know the size of the control here, we restrict the font scale to make sure the arrow will fit vertically in the bounds 820 float fontScale = min(o->style()->fontSize() / baseFontSize, bounds.height() / baseArrowHeight); 821 float centerY = bounds.y() + bounds.height() / 2.0f; 822 float arrowHeight = baseArrowHeight * fontScale; 823 float arrowWidth = baseArrowWidth * fontScale; 824 float leftEdge = bounds.maxX() - arrowPaddingRight - arrowWidth; 825 826 if (bounds.width() < arrowWidth + arrowPaddingLeft) 827 return false; 828 829 paintInfo.context->save(); 830 831 paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB); 832 paintInfo.context->setStrokeColor(NoStroke, ColorSpaceDeviceRGB); 833 834 FloatPoint arrow[3]; 835 arrow[0] = FloatPoint(leftEdge, centerY - arrowHeight / 2.0f); 836 arrow[1] = FloatPoint(leftEdge + arrowWidth, centerY - arrowHeight / 2.0f); 837 arrow[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + arrowHeight / 2.0f); 838 839 // Draw the arrow 840 paintInfo.context->drawConvexPolygon(3, arrow, true); 841 842 Color leftSeparatorColor(0, 0, 0, 40); 843 Color rightSeparatorColor(255, 255, 255, 40); 844 845 // FIXME: Should the separator thickness and space be scaled up by fontScale? 846 int separatorSpace = 2; 847 int leftEdgeOfSeparator = static_cast<int>(leftEdge - arrowPaddingLeft); // FIXME: Round? 848 849 // Draw the separator to the left of the arrows 850 paintInfo.context->setStrokeThickness(1.0f); 851 paintInfo.context->setStrokeStyle(SolidStroke); 852 paintInfo.context->setStrokeColor(leftSeparatorColor, ColorSpaceDeviceRGB); 853 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()), 854 IntPoint(leftEdgeOfSeparator, bounds.maxY())); 855 856 paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB); 857 paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()), 858 IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY())); 859 860 paintInfo.context->restore(); 861 return false; 862} 863 864void RenderThemeSafari::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const 865{ 866 NSControlSize controlSize = controlSizeForFont(style); 867 868 style->resetBorder(); 869 style->resetPadding(); 870 871 // Height is locked to auto. 872 style->setHeight(Length(Auto)); 873 874 // White-space is locked to pre 875 style->setWhiteSpace(PRE); 876 877 // Set the foreground color to black or gray when we have the aqua look. 878 // Cast to RGB32 is to work around a compiler bug. 879 style->setColor(e && !e->isDisabledFormControl() ? static_cast<RGBA32>(Color::black) : Color::darkGray); 880 881 // Set the button's vertical size. 882 setButtonSize(style); 883 884 // Our font is locked to the appropriate system font size for the control. To clarify, we first use the CSS-specified font to figure out 885 // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate 886 // system font for the control size instead. 887 setFontFromControlSize(styleResolver, style, controlSize); 888} 889 890int RenderThemeSafari::popupInternalPaddingLeft(RenderStyle* style) const 891{ 892 if (style->appearance() == MenulistPart) 893 return popupButtonPadding(controlSizeForFont(style))[leftPadding]; 894 if (style->appearance() == MenulistButtonPart) 895 return styledPopupPaddingLeft; 896 return 0; 897} 898 899int RenderThemeSafari::popupInternalPaddingRight(RenderStyle* style) const 900{ 901 if (style->appearance() == MenulistPart) 902 return popupButtonPadding(controlSizeForFont(style))[rightPadding]; 903 if (style->appearance() == MenulistButtonPart) { 904 float fontScale = style->fontSize() / baseFontSize; 905 float arrowWidth = baseArrowWidth * fontScale; 906 return static_cast<int>(ceilf(arrowWidth + arrowPaddingLeft + arrowPaddingRight + paddingBeforeSeparator)); 907 } 908 return 0; 909} 910 911int RenderThemeSafari::popupInternalPaddingTop(RenderStyle* style) const 912{ 913 if (style->appearance() == MenulistPart) 914 return popupButtonPadding(controlSizeForFont(style))[topPadding]; 915 if (style->appearance() == MenulistButtonPart) 916 return styledPopupPaddingTop; 917 return 0; 918} 919 920int RenderThemeSafari::popupInternalPaddingBottom(RenderStyle* style) const 921{ 922 if (style->appearance() == MenulistPart) 923 return popupButtonPadding(controlSizeForFont(style))[bottomPadding]; 924 if (style->appearance() == MenulistButtonPart) 925 return styledPopupPaddingBottom; 926 return 0; 927} 928 929void RenderThemeSafari::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) const 930{ 931 float fontScale = style->fontSize() / baseFontSize; 932 933 style->resetPadding(); 934 style->setBorderRadius(IntSize(int(baseBorderRadius + fontScale - 1), int(baseBorderRadius + fontScale - 1))); // FIXME: Round up? 935 936 const int minHeight = 15; 937 style->setMinHeight(Length(minHeight, Fixed)); 938 939 style->setLineHeight(RenderStyle::initialLineHeight()); 940} 941 942const IntSize* RenderThemeSafari::menuListSizes() const 943{ 944 static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) }; 945 return sizes; 946} 947 948int RenderThemeSafari::minimumMenuListSize(RenderStyle* style) const 949{ 950 return sizeForSystemFont(style, menuListSizes()).width(); 951} 952 953const int trackWidth = 5; 954const int trackRadius = 2; 955 956bool RenderThemeSafari::paintSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 957{ 958 IntSize radius(trackRadius, trackRadius); 959 RoundedRect bounds(r, radius, radius, radius, radius); 960 961 if (o->style()->appearance() == SliderHorizontalPart) 962 bounds.setRect(IntRect(r.x(), 963 r.y() + r.height() / 2 - trackWidth / 2, 964 r.width(), 965 trackWidth)); 966 else if (o->style()->appearance() == SliderVerticalPart) 967 bounds.setRect(IntRect(r.x() + r.width() / 2 - trackWidth / 2, 968 r.y(), 969 trackWidth, 970 r.height())); 971 972 CGContextRef context = paintInfo.context->platformContext(); 973 CGColorSpaceRef cspace = deviceRGBColorSpaceRef(); 974 975 paintInfo.context->save(); 976 CGContextClipToRect(context, bounds.rect()); 977 978 struct CGFunctionCallbacks mainCallbacks = { 0, TrackGradientInterpolate, NULL }; 979 RetainPtr<CGFunctionRef> mainFunction = adoptCF(CGFunctionCreate(NULL, 1, NULL, 4, NULL, &mainCallbacks)); 980 RetainPtr<CGShadingRef> mainShading; 981 if (o->style()->appearance() == SliderVerticalPart) 982 mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.rect().x(), bounds.rect().maxY()), CGPointMake(bounds.rect().maxX(), bounds.rect().maxY()), mainFunction.get(), false, false)); 983 else 984 mainShading = adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.rect().x(), bounds.rect().y()), CGPointMake(bounds.rect().x(), bounds.rect().maxY()), mainFunction.get(), false, false)); 985 986 paintInfo.context->clipRoundedRect(bounds); 987 CGContextDrawShading(context, mainShading.get()); 988 paintInfo.context->restore(); 989 990 return false; 991} 992 993void RenderThemeSafari::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const 994{ 995 RenderTheme::adjustSliderThumbStyle(styleResolver, style, e); 996 style->setBoxShadow(nullptr); 997} 998 999const float verticalSliderHeightPadding = 0.1f; 1000 1001bool RenderThemeSafari::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1002{ 1003 ASSERT(SafariThemeLibrary()); 1004 paintThemePart(SliderThumbPart, paintInfo.context->platformContext(), r, NSSmallControlSize, determineState(o)); 1005 return false; 1006} 1007 1008const int sliderThumbWidth = 15; 1009const int sliderThumbHeight = 15; 1010 1011void RenderThemeSafari::adjustSliderThumbSize(RenderStyle* style, Element*) const 1012{ 1013 if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) { 1014 style->setWidth(Length(sliderThumbWidth, Fixed)); 1015 style->setHeight(Length(sliderThumbHeight, Fixed)); 1016 } 1017#if ENABLE(VIDEO) 1018 else if (style->appearance() == MediaSliderThumbPart) 1019 RenderMediaControls::adjustMediaSliderThumbSize(style); 1020#endif 1021} 1022 1023bool RenderThemeSafari::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1024{ 1025 ASSERT(SafariThemeLibrary()); 1026 1027 paintThemePart(SafariTheme::SearchFieldPart, paintInfo.context->platformContext(), r, controlSizeFromRect(r, searchFieldSizes()), determineState(o)); 1028 return false; 1029} 1030 1031const IntSize* RenderThemeSafari::searchFieldSizes() const 1032{ 1033 static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 15) }; 1034 return sizes; 1035} 1036 1037void RenderThemeSafari::setSearchFieldSize(RenderStyle* style) const 1038{ 1039 // If the width and height are both specified, then we have nothing to do. 1040 if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) 1041 return; 1042 1043 // Use the font size to determine the intrinsic width of the control. 1044 setSizeFromFont(style, searchFieldSizes()); 1045} 1046 1047void RenderThemeSafari::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const 1048{ 1049 // Override border. 1050 style->resetBorder(); 1051 const short borderWidth = 2; 1052 style->setBorderLeftWidth(borderWidth); 1053 style->setBorderLeftStyle(INSET); 1054 style->setBorderRightWidth(borderWidth); 1055 style->setBorderRightStyle(INSET); 1056 style->setBorderBottomWidth(borderWidth); 1057 style->setBorderBottomStyle(INSET); 1058 style->setBorderTopWidth(borderWidth); 1059 style->setBorderTopStyle(INSET); 1060 1061 // Override height. 1062 style->setHeight(Length(Auto)); 1063 setSearchFieldSize(style); 1064 1065 // Override padding size to match AppKit text positioning. 1066 const int padding = 1; 1067 style->setPaddingLeft(Length(padding, Fixed)); 1068 style->setPaddingRight(Length(padding, Fixed)); 1069 style->setPaddingTop(Length(padding, Fixed)); 1070 style->setPaddingBottom(Length(padding, Fixed)); 1071 1072 NSControlSize controlSize = controlSizeForFont(style); 1073 setFontFromControlSize(styleResolver, style, controlSize); 1074} 1075 1076bool RenderThemeSafari::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect&) 1077{ 1078 ASSERT(SafariThemeLibrary()); 1079 1080 Node* input = o->node()->shadowHost(); 1081 if (!input) 1082 input = o->node(); 1083 RenderObject* renderer = input->renderer(); 1084 ASSERT(renderer); 1085 1086 IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms(); 1087 1088 paintThemePart(SafariTheme::SearchFieldCancelButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o)); 1089 return false; 1090} 1091 1092const IntSize* RenderThemeSafari::cancelButtonSizes() const 1093{ 1094 static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) }; 1095 return sizes; 1096} 1097 1098void RenderThemeSafari::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const 1099{ 1100 IntSize size = sizeForSystemFont(style, cancelButtonSizes()); 1101 style->setWidth(Length(size.width(), Fixed)); 1102 style->setHeight(Length(size.height(), Fixed)); 1103} 1104 1105const IntSize* RenderThemeSafari::resultsButtonSizes() const 1106{ 1107 static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) }; 1108 return sizes; 1109} 1110 1111const int emptyResultsOffset = 9; 1112void RenderThemeSafari::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const 1113{ 1114 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1115 style->setWidth(Length(size.width() - emptyResultsOffset, Fixed)); 1116 style->setHeight(Length(size.height(), Fixed)); 1117} 1118 1119bool RenderThemeSafari::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) 1120{ 1121 return false; 1122} 1123 1124void RenderThemeSafari::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const 1125{ 1126 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1127 style->setWidth(Length(size.width(), Fixed)); 1128 style->setHeight(Length(size.height(), Fixed)); 1129} 1130 1131bool RenderThemeSafari::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect&) 1132{ 1133 ASSERT(SafariThemeLibrary()); 1134 1135 Node* input = o->node()->shadowHost(); 1136 if (!input) 1137 input = o->node(); 1138 RenderObject* renderer = input->renderer(); 1139 ASSERT(renderer); 1140 1141 IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms(); 1142 1143 paintThemePart(SafariTheme::SearchFieldResultsDecorationPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o)); 1144 return false; 1145} 1146 1147const int resultsArrowWidth = 5; 1148void RenderThemeSafari::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const 1149{ 1150 IntSize size = sizeForSystemFont(style, resultsButtonSizes()); 1151 style->setWidth(Length(size.width() + resultsArrowWidth, Fixed)); 1152 style->setHeight(Length(size.height(), Fixed)); 1153} 1154 1155bool RenderThemeSafari::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect&) 1156{ 1157 ASSERT(SafariThemeLibrary()); 1158 1159 Node* input = o->node()->shadowHost(); 1160 if (!input) 1161 input = o->node(); 1162 RenderObject* renderer = input->renderer(); 1163 ASSERT(renderer); 1164 1165 IntRect searchRect = renderer->absoluteBoundingBoxRectIgnoringTransforms(); 1166 1167 paintThemePart(SafariTheme::SearchFieldResultsButtonPart, paintInfo.context->platformContext(), searchRect, controlSizeFromRect(searchRect, searchFieldSizes()), determineState(o)); 1168 return false; 1169} 1170#if ENABLE(VIDEO) 1171bool RenderThemeSafari::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1172{ 1173 return RenderMediaControls::paintMediaControlsPart(MediaEnterFullscreenButton, o, paintInfo, r); 1174} 1175 1176bool RenderThemeSafari::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1177{ 1178 return RenderMediaControls::paintMediaControlsPart(MediaMuteButton, o, paintInfo, r); 1179} 1180 1181bool RenderThemeSafari::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1182{ 1183 return RenderMediaControls::paintMediaControlsPart(MediaPlayButton, o, paintInfo, r); 1184} 1185 1186bool RenderThemeSafari::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1187{ 1188 return RenderMediaControls::paintMediaControlsPart(MediaSeekBackButton, o, paintInfo, r); 1189} 1190 1191bool RenderThemeSafari::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1192{ 1193 return RenderMediaControls::paintMediaControlsPart(MediaSeekForwardButton, o, paintInfo, r); 1194} 1195 1196bool RenderThemeSafari::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1197{ 1198 return RenderMediaControls::paintMediaControlsPart(MediaSlider, o, paintInfo, r); 1199} 1200 1201bool RenderThemeSafari::paintMediaSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 1202{ 1203 return RenderMediaControls::paintMediaControlsPart(MediaSliderThumb, o, paintInfo, r); 1204} 1205#endif 1206 1207#if ENABLE(METER_ELEMENT) 1208void RenderThemeSafari::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const 1209{ 1210 style->setBoxShadow(nullptr); 1211} 1212 1213bool RenderThemeSafari::supportsMeter(ControlPart part) const 1214{ 1215 switch (part) { 1216 case MeterPart: 1217 return true; 1218 default: 1219 return false; 1220 } 1221} 1222 1223IntSize RenderThemeSafari::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const 1224{ 1225 return bounds.size(); 1226} 1227 1228bool RenderThemeSafari::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect) 1229{ 1230 // NOTE: This routine is for testing only. It should be fleshed out with a real CG-based implementation. 1231 // Right now it uses a slider, with the thumb positioned at the meter point. 1232 if (!renderObject->isMeter()) 1233 return true; 1234 1235 HTMLMeterElement* element = toRenderMeter(renderObject)->meterElement(); 1236 1237 int remaining = static_cast<int>((1.0 - element->valueRatio()) * static_cast<double>(rect.size().width())); 1238 1239 // Draw the background 1240 paintSliderTrack(renderObject, paintInfo, rect); 1241 1242 // Draw the progress portion 1243 IntRect completedRect(rect); 1244 completedRect.contract(remaining, 0); 1245 1246 paintSliderThumb(renderObject, paintInfo, completedRect); 1247 1248 return true; 1249} 1250 1251#endif 1252 1253} // namespace WebCore 1254 1255#endif // #if USE(SAFARI_THEME) 1256