| /* |
| * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
| * Copyright (C) 2008, 2009 Google, Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #import "core/paint/ThemePainterMac.h" |
| |
| #import "core/layout/LayoutProgress.h" |
| #import "core/layout/LayoutThemeMac.h" |
| #import "core/layout/LayoutView.h" |
| #import "core/paint/PaintInfo.h" |
| #import "platform/geometry/FloatRoundedRect.h" |
| #import "platform/graphics/BitmapImage.h" |
| #import "platform/graphics/GraphicsContextStateSaver.h" |
| #import "platform/graphics/Image.h" |
| #import "platform/graphics/ImageBuffer.h" |
| #import "platform/mac/ColorMac.h" |
| #import "platform/mac/LocalCurrentGraphicsContext.h" |
| #import "platform/mac/ThemeMac.h" |
| #import "platform/mac/WebCoreNSCellExtras.h" |
| #import <AvailabilityMacros.h> |
| #import <Carbon/Carbon.h> |
| #import <Cocoa/Cocoa.h> |
| #import <math.h> |
| |
| // The methods in this file are specific to the Mac OS X platform. |
| |
| // Forward declare Mac SPIs. |
| extern "C" { |
| void _NSDrawCarbonThemeBezel(NSRect frame, BOOL enabled, BOOL flipped); |
| // Request for public API: rdar://13787640 |
| void _NSDrawCarbonThemeListBox(NSRect frame, BOOL enabled, BOOL flipped, BOOL always_yes); |
| } |
| |
| namespace blink { |
| |
| ThemePainterMac::ThemePainterMac(LayoutThemeMac& layoutTheme, Theme* platformTheme) |
| : ThemePainter(platformTheme) |
| , m_layoutTheme(layoutTheme) |
| { |
| } |
| |
| bool ThemePainterMac::paintTextField(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| LocalCurrentGraphicsContext localContext(paintInfo.context, r); |
| |
| #if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 |
| bool useNSTextFieldCell = o.styleRef().hasAppearance() |
| && o.styleRef().visitedDependentColor(CSSPropertyBackgroundColor) == Color::white |
| && !o.styleRef().hasBackgroundImage(); |
| |
| // We do not use NSTextFieldCell to draw styled text fields on Lion and |
| // SnowLeopard because there are a number of bugs on those platforms that |
| // require NSTextFieldCell to be in charge of painting its own |
| // background. We need WebCore to paint styled backgrounds, so we'll use |
| // this AppKit SPI function instead. |
| if (!useNSTextFieldCell) { |
| _NSDrawCarbonThemeBezel(r, LayoutTheme::isEnabled(o) && !LayoutTheme::isReadOnlyControl(o), YES); |
| return false; |
| } |
| #endif |
| |
| NSTextFieldCell *textField = m_layoutTheme.textField(); |
| |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| |
| [textField setEnabled:(LayoutTheme::isEnabled(o) && !LayoutTheme::isReadOnlyControl(o))]; |
| [textField drawWithFrame:NSRect(r) inView:m_layoutTheme.documentViewFor(o)]; |
| |
| [textField setControlView:nil]; |
| |
| return false; |
| } |
| |
| bool ThemePainterMac::paintCapsLockIndicator(const LayoutObject&, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| // This draws the caps lock indicator as it was done by |
| // WKDrawCapsLockIndicator. |
| LocalCurrentGraphicsContext localContext(paintInfo.context, r); |
| CGContextRef c = localContext.cgContext(); |
| CGMutablePathRef shape = CGPathCreateMutable(); |
| |
| // To draw the caps lock indicator, draw the shape into a small |
| // square that is then scaled to the size of r. |
| const CGFloat kSquareSize = 17; |
| |
| // Create a rounted square shape. |
| CGPathMoveToPoint(shape, NULL, 16.5, 4.5); |
| CGPathAddArc(shape, NULL, 12.5, 12.5, 4, 0, M_PI_2, false); |
| CGPathAddArc(shape, NULL, 4.5, 12.5, 4, M_PI_2, M_PI, false); |
| CGPathAddArc(shape, NULL, 4.5, 4.5, 4, M_PI, 3*M_PI/2, false); |
| CGPathAddArc(shape, NULL, 12.5, 4.5, 4, 3*M_PI/2, 0, false); |
| |
| // Draw the arrow - note this is drawing in a flipped coordinate system, so |
| // the arrow is pointing down. |
| CGPathMoveToPoint(shape, NULL, 8.5, 2); // Tip point. |
| CGPathAddLineToPoint(shape, NULL, 4, 7); |
| CGPathAddLineToPoint(shape, NULL, 6.25, 7); |
| CGPathAddLineToPoint(shape, NULL, 6.25, 10.25); |
| CGPathAddLineToPoint(shape, NULL, 10.75, 10.25); |
| CGPathAddLineToPoint(shape, NULL, 10.75, 7); |
| CGPathAddLineToPoint(shape, NULL, 13, 7); |
| CGPathAddLineToPoint(shape, NULL, 8.5, 2); |
| |
| // Draw the rectangle that underneath (or above in the flipped system) the |
| // arrow. |
| CGPathAddLineToPoint(shape, NULL, 10.75, 12); |
| CGPathAddLineToPoint(shape, NULL, 6.25, 12); |
| CGPathAddLineToPoint(shape, NULL, 6.25, 14.25); |
| CGPathAddLineToPoint(shape, NULL, 10.75, 14.25); |
| CGPathAddLineToPoint(shape, NULL, 10.75, 12); |
| |
| // Scale and translate the shape. |
| CGRect cgr = r; |
| CGFloat maxX = CGRectGetMaxX(cgr); |
| CGFloat minY = CGRectGetMinY(cgr); |
| CGFloat heightScale = r.height() / kSquareSize; |
| CGAffineTransform transform = CGAffineTransformMake( |
| heightScale, 0, // A B |
| 0, heightScale, // C D |
| maxX - r.height(), minY); // Tx Ty |
| |
| CGMutablePathRef paintPath = CGPathCreateMutable(); |
| CGPathAddPath(paintPath, &transform, shape); |
| CGPathRelease(shape); |
| |
| CGContextSetRGBFillColor(c, 0, 0, 0, 0.4); |
| CGContextBeginPath(c); |
| CGContextAddPath(c, paintPath); |
| CGContextFillPath(c); |
| CGPathRelease(paintPath); |
| |
| return false; |
| } |
| |
| bool ThemePainterMac::paintTextArea(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| LocalCurrentGraphicsContext localContext(paintInfo.context, r); |
| _NSDrawCarbonThemeListBox(r, LayoutTheme::isEnabled(o) && !LayoutTheme::isReadOnlyControl(o), YES, YES); |
| return false; |
| } |
| |
| bool ThemePainterMac::paintMenuList(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| m_layoutTheme.setPopupButtonCellState(o, r); |
| |
| NSPopUpButtonCell* popupButton = m_layoutTheme.popupButton(); |
| |
| float zoomLevel = o.styleRef().effectiveZoom(); |
| IntSize size = m_layoutTheme.popupButtonSizes()[[popupButton controlSize]]; |
| size.setHeight(size.height() * zoomLevel); |
| size.setWidth(r.width()); |
| |
| // Now inflate it to account for the shadow. |
| IntRect inflatedRect = r; |
| if (r.width() >= m_layoutTheme.minimumMenuListSize(o.styleRef())) |
| inflatedRect = ThemeMac::inflateRect(inflatedRect, size, m_layoutTheme.popupButtonMargins(), zoomLevel); |
| |
| LocalCurrentGraphicsContext localContext(paintInfo.context, ThemeMac::inflateRectForFocusRing(inflatedRect)); |
| |
| if (zoomLevel != 1.0f) { |
| inflatedRect.setWidth(inflatedRect.width() / zoomLevel); |
| inflatedRect.setHeight(inflatedRect.height() / zoomLevel); |
| paintInfo.context.translate(inflatedRect.x(), inflatedRect.y()); |
| paintInfo.context.scale(zoomLevel, zoomLevel); |
| paintInfo.context.translate(-inflatedRect.x(), -inflatedRect.y()); |
| } |
| |
| NSView *view = m_layoutTheme.documentViewFor(o); |
| [popupButton drawWithFrame:inflatedRect inView:view]; |
| if (!ThemeMac::drawWithFrameDrawsFocusRing() && LayoutTheme::isFocused(o) && o.styleRef().outlineStyleIsAuto()) |
| [popupButton cr_drawFocusRingWithFrame:inflatedRect inView:view]; |
| [popupButton setControlView:nil]; |
| |
| return false; |
| } |
| |
| bool ThemePainterMac::paintProgressBar(const LayoutObject& layoutObject, const PaintInfo& paintInfo, const IntRect& rect) |
| { |
| if (!layoutObject.isProgress()) |
| return true; |
| |
| float zoomLevel = layoutObject.styleRef().effectiveZoom(); |
| NSControlSize controlSize = m_layoutTheme.controlSizeForFont(layoutObject.styleRef()); |
| IntSize size = m_layoutTheme.progressBarSizes()[controlSize]; |
| size.setHeight(size.height() * zoomLevel); |
| size.setWidth(rect.width()); |
| |
| // Now inflate it to account for the shadow. |
| IntRect inflatedRect = rect; |
| if (rect.height() <= m_layoutTheme.minimumProgressBarHeight(layoutObject.styleRef())) |
| inflatedRect = ThemeMac::inflateRect(inflatedRect, size, m_layoutTheme.progressBarMargins(controlSize), zoomLevel); |
| |
| const LayoutProgress& layoutProgress = toLayoutProgress(layoutObject); |
| HIThemeTrackDrawInfo trackInfo; |
| trackInfo.version = 0; |
| if (controlSize == NSRegularControlSize) |
| trackInfo.kind = layoutProgress.position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar; |
| else |
| trackInfo.kind = layoutProgress.position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar; |
| |
| trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size()); |
| trackInfo.min = 0; |
| trackInfo.max = std::numeric_limits<SInt32>::max(); |
| trackInfo.value = lround(layoutProgress.position() * nextafter(trackInfo.max, 0)); |
| trackInfo.trackInfo.progress.phase = lround(layoutProgress.animationProgress() * nextafter(LayoutThemeMac::progressAnimationNumFrames, 0)); |
| trackInfo.attributes = kThemeTrackHorizontal; |
| trackInfo.enableState = LayoutTheme::isActive(layoutObject) ? kThemeTrackActive : kThemeTrackInactive; |
| trackInfo.reserved = 0; |
| trackInfo.filler1 = 0; |
| |
| OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size()); |
| if (!imageBuffer) |
| return true; |
| |
| IntRect clipRect = IntRect(IntPoint(), inflatedRect.size()); |
| LocalCurrentGraphicsContext localContext(imageBuffer->canvas(), 1, clipRect); |
| CGContextRef cgContext = localContext.cgContext(); |
| HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal); |
| |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| |
| if (!layoutProgress.styleRef().isLeftToRightDirection()) { |
| paintInfo.context.translate(2 * inflatedRect.x() + inflatedRect.width(), 0); |
| paintInfo.context.scale(-1, 1); |
| } |
| |
| if (!paintInfo.context.contextDisabled()) |
| imageBuffer->draw(paintInfo.context, FloatRect(inflatedRect.location(), FloatSize(imageBuffer->size())), nullptr, SkXfermode::kSrcOver_Mode); |
| return false; |
| } |
| |
| bool ThemePainterMac::paintMenuListButton(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| IntRect bounds = IntRect(r.x() + o.styleRef().borderLeftWidth(), |
| r.y() + o.styleRef().borderTopWidth(), |
| r.width() - o.styleRef().borderLeftWidth() - o.styleRef().borderRightWidth(), |
| r.height() - o.styleRef().borderTopWidth() - o.styleRef().borderBottomWidth()); |
| // Since we actually know the size of the control here, we restrict the font |
| // scale to make sure the arrows will fit vertically in the bounds |
| float fontScale = std::min(o.styleRef().fontSize() / LayoutThemeMac::baseFontSize, |
| bounds.height() / (LayoutThemeMac::menuListBaseArrowHeight * 2 + LayoutThemeMac::menuListBaseSpaceBetweenArrows)); |
| float centerY = bounds.y() + bounds.height() / 2.0f; |
| float arrowHeight = LayoutThemeMac::menuListBaseArrowHeight * fontScale; |
| float arrowWidth = LayoutThemeMac::menuListBaseArrowWidth * fontScale; |
| float leftEdge = bounds.maxX() - LayoutThemeMac::menuListArrowPaddingRight * o.styleRef().effectiveZoom() - arrowWidth; |
| float spaceBetweenArrows = LayoutThemeMac::menuListBaseSpaceBetweenArrows * fontScale; |
| |
| if (bounds.width() < arrowWidth + LayoutThemeMac::menuListArrowPaddingLeft * o.styleRef().effectiveZoom()) |
| return false; |
| |
| Color color = o.styleRef().visitedDependentColor(CSSPropertyColor); |
| |
| FloatPoint arrow1[3]; |
| arrow1[0] = FloatPoint(leftEdge, centerY - spaceBetweenArrows / 2.0f); |
| arrow1[1] = FloatPoint(leftEdge + arrowWidth, centerY - spaceBetweenArrows / 2.0f); |
| arrow1[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY - spaceBetweenArrows / 2.0f - arrowHeight); |
| |
| // Draw the top arrow. |
| paintInfo.context.fillPolygon(3, arrow1, color, true); |
| |
| FloatPoint arrow2[3]; |
| arrow2[0] = FloatPoint(leftEdge, centerY + spaceBetweenArrows / 2.0f); |
| arrow2[1] = FloatPoint(leftEdge + arrowWidth, centerY + spaceBetweenArrows / 2.0f); |
| arrow2[2] = FloatPoint(leftEdge + arrowWidth / 2.0f, centerY + spaceBetweenArrows / 2.0f + arrowHeight); |
| |
| // Draw the bottom arrow. |
| paintInfo.context.fillPolygon(3, arrow2, color, true); |
| return false; |
| } |
| |
| bool ThemePainterMac::paintSliderTrack(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| paintSliderTicks(o, paintInfo, r); |
| |
| float zoomLevel = o.styleRef().effectiveZoom(); |
| FloatRect unzoomedRect = r; |
| |
| if (o.styleRef().appearance() == SliderHorizontalPart || o.styleRef().appearance() == MediaSliderPart) { |
| unzoomedRect.setY(ceilf(unzoomedRect.y() + unzoomedRect.height() / 2 - zoomLevel * LayoutThemeMac::sliderTrackWidth / 2)); |
| unzoomedRect.setHeight(zoomLevel * LayoutThemeMac::sliderTrackWidth); |
| } else if (o.styleRef().appearance() == SliderVerticalPart) { |
| unzoomedRect.setX(ceilf(unzoomedRect.x() + unzoomedRect.width() / 2 - zoomLevel * LayoutThemeMac::sliderTrackWidth / 2)); |
| unzoomedRect.setWidth(zoomLevel * LayoutThemeMac::sliderTrackWidth); |
| } |
| |
| if (zoomLevel != 1) { |
| unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); |
| unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); |
| } |
| |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| if (zoomLevel != 1) { |
| paintInfo.context.translate(unzoomedRect.x(), unzoomedRect.y()); |
| paintInfo.context.scale(zoomLevel, zoomLevel); |
| paintInfo.context.translate(-unzoomedRect.x(), -unzoomedRect.y()); |
| } |
| |
| Color fillColor(205, 205, 205); |
| Color borderGradientTopColor(109, 109, 109); |
| Color borderGradientBottomColor(181, 181, 181); |
| Color shadowColor(0, 0, 0, 118); |
| |
| if (!LayoutTheme::isEnabled(o)) { |
| Color tintColor(255, 255, 255, 128); |
| fillColor = fillColor.blend(tintColor); |
| borderGradientTopColor = borderGradientTopColor.blend(tintColor); |
| borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); |
| shadowColor = shadowColor.blend(tintColor); |
| } |
| |
| Color tintColor; |
| if (!LayoutTheme::isEnabled(o)) |
| tintColor = Color(255, 255, 255, 128); |
| |
| bool isVerticalSlider = o.styleRef().appearance() == SliderVerticalPart; |
| |
| float fillRadiusSize = (LayoutThemeMac::sliderTrackWidth - LayoutThemeMac::sliderTrackBorderWidth) / 2; |
| FloatSize fillRadius(fillRadiusSize, fillRadiusSize); |
| FloatRect fillBounds(enclosedIntRect(unzoomedRect)); |
| FloatRoundedRect fillRect(fillBounds, fillRadius, fillRadius, fillRadius, fillRadius); |
| paintInfo.context.fillRoundedRect(fillRect, fillColor); |
| |
| FloatSize shadowOffset(isVerticalSlider ? 1 : 0, |
| isVerticalSlider ? 0 : 1); |
| float shadowBlur = 3; |
| float shadowSpread = 0; |
| paintInfo.context.save(); |
| paintInfo.context.drawInnerShadow(fillRect, shadowColor, shadowOffset, shadowBlur, shadowSpread); |
| paintInfo.context.restore(); |
| |
| RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(), |
| isVerticalSlider ? fillBounds.maxXMinYCorner() : fillBounds.minXMaxYCorner()); |
| borderGradient->addColorStop(0.0, borderGradientTopColor); |
| borderGradient->addColorStop(1.0, borderGradientBottomColor); |
| |
| FloatRect borderRect(unzoomedRect); |
| borderRect.inflate(-LayoutThemeMac::sliderTrackBorderWidth / 2.0); |
| float borderRadiusSize = (isVerticalSlider ? borderRect.width() : borderRect.height()) / 2; |
| FloatSize borderRadius(borderRadiusSize, borderRadiusSize); |
| FloatRoundedRect borderRRect(borderRect, borderRadius, borderRadius, borderRadius, borderRadius); |
| paintInfo.context.setStrokeThickness(LayoutThemeMac::sliderTrackBorderWidth); |
| SkPaint borderPaint(paintInfo.context.strokePaint()); |
| borderGradient->applyToPaint(borderPaint); |
| paintInfo.context.drawRRect(borderRRect, borderPaint); |
| |
| return false; |
| } |
| |
| |
| bool ThemePainterMac::paintSliderThumb(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| float zoomLevel = o.styleRef().effectiveZoom(); |
| |
| FloatRect unzoomedRect(r.x(), r.y(), LayoutThemeMac::sliderThumbWidth, LayoutThemeMac::sliderThumbHeight); |
| if (zoomLevel != 1.0f) { |
| paintInfo.context.translate(unzoomedRect.x(), unzoomedRect.y()); |
| paintInfo.context.scale(zoomLevel, zoomLevel); |
| paintInfo.context.translate(-unzoomedRect.x(), -unzoomedRect.y()); |
| } |
| |
| Color fillGradientTopColor(250, 250, 250); |
| Color fillGradientUpperMiddleColor(244, 244, 244); |
| Color fillGradientLowerMiddleColor(236, 236, 236); |
| Color fillGradientBottomColor(238, 238, 238); |
| Color borderGradientTopColor(151, 151, 151); |
| Color borderGradientBottomColor(128, 128, 128); |
| Color shadowColor(0, 0, 0, 36); |
| |
| if (!LayoutTheme::isEnabled(o)) { |
| Color tintColor(255, 255, 255, 128); |
| fillGradientTopColor = fillGradientTopColor.blend(tintColor); |
| fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor); |
| fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor); |
| fillGradientBottomColor = fillGradientBottomColor.blend(tintColor); |
| borderGradientTopColor = borderGradientTopColor.blend(tintColor); |
| borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); |
| shadowColor = shadowColor.blend(tintColor); |
| } else if (LayoutTheme::isPressed(o)) { |
| Color tintColor(0, 0, 0, 32); |
| fillGradientTopColor = fillGradientTopColor.blend(tintColor); |
| fillGradientUpperMiddleColor = fillGradientUpperMiddleColor.blend(tintColor); |
| fillGradientLowerMiddleColor = fillGradientLowerMiddleColor.blend(tintColor); |
| fillGradientBottomColor = fillGradientBottomColor.blend(tintColor); |
| borderGradientTopColor = borderGradientTopColor.blend(tintColor); |
| borderGradientBottomColor = borderGradientBottomColor.blend(tintColor); |
| shadowColor = shadowColor.blend(tintColor); |
| } |
| |
| FloatRect borderBounds = unzoomedRect; |
| borderBounds.inflate(LayoutThemeMac::sliderThumbBorderWidth / 2.0); |
| |
| borderBounds.inflate(-LayoutThemeMac::sliderThumbBorderWidth); |
| FloatSize shadowOffset(0, 1); |
| paintInfo.context.setShadow(shadowOffset, LayoutThemeMac::sliderThumbShadowBlur, shadowColor); |
| paintInfo.context.setFillColor(Color::black); |
| paintInfo.context.fillEllipse(borderBounds); |
| paintInfo.context.setDrawLooper(nullptr); |
| |
| IntRect fillBounds = enclosedIntRect(unzoomedRect); |
| RefPtr<Gradient> fillGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner()); |
| fillGradient->addColorStop(0.0, fillGradientTopColor); |
| fillGradient->addColorStop(0.52, fillGradientUpperMiddleColor); |
| fillGradient->addColorStop(0.52, fillGradientLowerMiddleColor); |
| fillGradient->addColorStop(1.0, fillGradientBottomColor); |
| SkPaint fillPaint(paintInfo.context.fillPaint()); |
| fillGradient->applyToPaint(fillPaint); |
| paintInfo.context.drawOval(borderBounds, fillPaint); |
| |
| RefPtr<Gradient> borderGradient = Gradient::create(fillBounds.minXMinYCorner(), fillBounds.minXMaxYCorner()); |
| borderGradient->addColorStop(0.0, borderGradientTopColor); |
| borderGradient->addColorStop(1.0, borderGradientBottomColor); |
| paintInfo.context.setStrokeThickness(LayoutThemeMac::sliderThumbBorderWidth); |
| SkPaint borderPaint(paintInfo.context.strokePaint()); |
| borderGradient->applyToPaint(borderPaint); |
| paintInfo.context.drawOval(borderBounds, borderPaint); |
| |
| if (LayoutTheme::isFocused(o)) { |
| Path borderPath; |
| borderPath.addEllipse(borderBounds); |
| paintInfo.context.drawFocusRing(borderPath, 5, -2, m_layoutTheme.focusRingColor()); |
| } |
| |
| return false; |
| } |
| |
| // We don't use controlSizeForFont() for search field decorations because it |
| // needs to fit into the search field. The font size will already be modified by |
| // setFontFromControlSize() called on the search field. |
| static NSControlSize searchFieldControlSizeForFont(const ComputedStyle& style) |
| { |
| int fontSize = style.fontSize(); |
| if (fontSize >= 13) |
| return NSRegularControlSize; |
| if (fontSize >= 11) |
| return NSSmallControlSize; |
| return NSMiniControlSize; |
| } |
| |
| bool ThemePainterMac::paintSearchField(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| LocalCurrentGraphicsContext localContext(paintInfo.context, r); |
| |
| NSSearchFieldCell* search = m_layoutTheme.search(); |
| m_layoutTheme.setSearchCellState(o, r); |
| [search setControlSize:searchFieldControlSizeForFont(o.styleRef())]; |
| |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| |
| float zoomLevel = o.styleRef().effectiveZoom(); |
| |
| IntRect unzoomedRect = r; |
| |
| if (zoomLevel != 1.0f) { |
| unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); |
| unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); |
| paintInfo.context.translate(unzoomedRect.x(), unzoomedRect.y()); |
| paintInfo.context.scale(zoomLevel, zoomLevel); |
| paintInfo.context.translate(-unzoomedRect.x(), -unzoomedRect.y()); |
| } |
| |
| // Set the search button to nil before drawing. Then reset it so we can |
| // draw it later. |
| [search setSearchButtonCell:nil]; |
| |
| [search drawWithFrame:NSRect(unzoomedRect) inView:m_layoutTheme.documentViewFor(o)]; |
| |
| [search setControlView:nil]; |
| [search resetSearchButtonCell]; |
| |
| return false; |
| } |
| |
| bool ThemePainterMac::paintSearchFieldCancelButton(const LayoutObject& o, const PaintInfo& paintInfo, const IntRect& r) |
| { |
| if (!o.node()) |
| return false; |
| Element* input = o.node()->shadowHost(); |
| if (!input) |
| input = toElement(o.node()); |
| |
| if (!input->layoutObject()->isBox()) |
| return false; |
| |
| GraphicsContextStateSaver stateSaver(paintInfo.context); |
| |
| float zoomLevel = o.styleRef().effectiveZoom(); |
| FloatRect unzoomedRect(r); |
| if (zoomLevel != 1.0f) { |
| unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); |
| unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); |
| paintInfo.context.translate(unzoomedRect.x(), unzoomedRect.y()); |
| paintInfo.context.scale(zoomLevel, zoomLevel); |
| paintInfo.context.translate(-unzoomedRect.x(), -unzoomedRect.y()); |
| } |
| |
| Color fillColor(200, 200, 200); |
| |
| if (LayoutTheme::isPressed(o)) { |
| Color tintColor(0, 0, 0, 32); |
| fillColor = fillColor.blend(tintColor); |
| } |
| |
| float centerX = unzoomedRect.x() + unzoomedRect.width() / 2; |
| float centerY = unzoomedRect.y() + unzoomedRect.height() / 2; |
| // The line width is 3px on a regular sized, high DPI NSCancelButtonCell |
| // (which is 28px wide). |
| float lineWidth = unzoomedRect.width() * 3 / 28; |
| // The line length is 16px on a regular sized, high DPI NSCancelButtonCell. |
| float lineLength = unzoomedRect.width() * 16 / 28; |
| |
| Path xPath; |
| FloatSize lineRectRadius(lineWidth / 2, lineWidth / 2); |
| xPath.addRoundedRect(FloatRect(-lineLength / 2, -lineWidth / 2, lineLength, lineWidth), |
| lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius); |
| xPath.addRoundedRect(FloatRect(-lineWidth / 2, -lineLength / 2, lineWidth, lineLength), |
| lineRectRadius, lineRectRadius, lineRectRadius, lineRectRadius); |
| |
| paintInfo.context.translate(centerX, centerY); |
| paintInfo.context.rotate(deg2rad(45.0)); |
| paintInfo.context.clipOut(xPath); |
| paintInfo.context.rotate(deg2rad(-45.0)); |
| paintInfo.context.translate(-centerX, -centerY); |
| |
| paintInfo.context.setFillColor(fillColor); |
| paintInfo.context.fillEllipse(unzoomedRect); |
| |
| return false; |
| } |
| |
| } // namespace blink |