1 /* 2 * Copyright (C) 2009 Apple Inc. All Rights Reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #if ENABLE(VIDEO) 29 30 #include "RenderMediaControls.h" 31 32 #include "GraphicsContext.h" 33 #include "HTMLMediaElement.h" 34 #include "HTMLNames.h" 35 #include "PaintInfo.h" 36 #include "RenderTheme.h" 37 38 // FIXME: Unify more of the code for Mac and Win. 39 #if PLATFORM(WIN) 40 41 #include <CoreGraphics/CoreGraphics.h> 42 #include <WebKitSystemInterface/WebKitSystemInterface.h> 43 44 // The Windows version of WKSI defines these functions as capitalized, while the Mac version defines them as lower case. 45 // FIXME: Is this necessary anymore? 46 #define wkMediaControllerThemeAvailable(themeStyle) WKMediaControllerThemeAvailable(themeStyle) 47 #define wkHitTestMediaUIPart(part, themeStyle, bounds, point) WKHitTestMediaUIPart(part, themeStyle, bounds, point) 48 #define wkMeasureMediaUIPart(part, themeStyle, bounds, naturalSize) WKMeasureMediaUIPart(part, themeStyle, bounds, naturalSize) 49 #define wkDrawMediaUIPart(part, themeStyle, context, rect, state) WKDrawMediaUIPart(part, themeStyle, context, rect, state) 50 #define wkDrawMediaSliderTrack(themeStyle, context, rect, timeLoaded, currentTime, duration, state) WKDrawMediaSliderTrack(themeStyle, context, rect, timeLoaded, currentTime, duration, state) 51 52 #endif 53 54 using namespace std; 55 56 namespace WebCore { 57 58 #if PLATFORM(WIN) 59 60 static WKMediaControllerThemeState determineState(RenderObject* o) 61 { 62 int result = 0; 63 RenderTheme* theme = o->theme(); 64 if (!theme->isEnabled(o) || theme->isReadOnlyControl(o)) 65 result |= WKMediaControllerFlagDisabled; 66 if (theme->isPressed(o)) 67 result |= WKMediaControllerFlagPressed; 68 if (theme->isFocused(o)) 69 result |= WKMediaControllerFlagFocused; 70 return static_cast<WKMediaControllerThemeState>(result); 71 } 72 73 // Utility to scale when the UI part are not scaled by wkDrawMediaUIPart 74 static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect) 75 { 76 float zoomLevel = o->style()->effectiveZoom(); 77 FloatRect unzoomedRect(originalRect); 78 if (zoomLevel != 1.0f) { 79 unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel); 80 unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel); 81 paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y()); 82 paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel)); 83 paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y()); 84 } 85 return unzoomedRect; 86 } 87 88 static const int mediaSliderThumbWidth = 13; 89 static const int mediaSliderThumbHeight = 14; 90 91 void RenderMediaControls::adjustMediaSliderThumbSize(RenderObject* o) 92 { 93 ControlPart part = o->style()->appearance(); 94 95 if (part != MediaSliderThumbPart && part != MediaVolumeSliderThumbPart) 96 return; 97 98 CGSize size; 99 wkMeasureMediaUIPart(part == MediaSliderThumbPart ? MediaSliderThumb : MediaVolumeSliderThumb, WKMediaControllerThemeQuickTime, 0, &size); 100 101 float zoomLevel = o->style()->effectiveZoom(); 102 o->style()->setWidth(Length(static_cast<int>(size.width * zoomLevel), Fixed)); 103 o->style()->setHeight(Length(static_cast<int>(size.height * zoomLevel), Fixed)); 104 } 105 106 bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, RenderObject* o, const PaintInfo& paintInfo, const IntRect& r) 107 { 108 static const int themeStyle = WKMediaControllerThemeQuickTime; 109 paintInfo.context->save(); 110 switch (part) { 111 case MediaFullscreenButton: 112 wkDrawMediaUIPart(WKMediaUIPartFullscreenButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 113 break; 114 case MediaShowClosedCaptionsButton: 115 case MediaHideClosedCaptionsButton: 116 if (MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(o->node())) { 117 bool captionsVisible = btn->displayType() == MediaHideClosedCaptionsButton; 118 wkDrawMediaUIPart(captionsVisible ? WKMediaUIPartHideClosedCaptionsButton : WKMediaUIPartShowClosedCaptionsButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 119 } 120 break; 121 case MediaMuteButton: 122 case MediaUnMuteButton: 123 if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) { 124 bool audioEnabled = btn->displayType() == MediaMuteButton; 125 wkDrawMediaUIPart(audioEnabled ? WKMediaUIPartMuteButton : WKMediaUIPartUnMuteButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 126 } 127 break; 128 case MediaPauseButton: 129 case MediaPlayButton: 130 if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) { 131 bool canPlay = btn->displayType() == MediaPlayButton; 132 wkDrawMediaUIPart(canPlay ? WKMediaUIPartPlayButton : WKMediaUIPartPauseButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 133 } 134 break; 135 case MediaRewindButton: 136 wkDrawMediaUIPart(WKMediaUIPartRewindButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 137 break; 138 case MediaSeekBackButton: 139 wkDrawMediaUIPart(WKMediaUIPartSeekBackButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 140 break; 141 case MediaSeekForwardButton: 142 wkDrawMediaUIPart(WKMediaUIPartSeekForwardButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 143 break; 144 case MediaSlider: { 145 if (HTMLMediaElement* mediaElement = toParentMediaElement(o)) { 146 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r); 147 wkDrawMediaSliderTrack(themeStyle, paintInfo.context->platformContext(), unzoomedRect, mediaElement->percentLoaded() * mediaElement->duration(), mediaElement->currentTime(), mediaElement->duration(), determineState(o)); 148 } 149 break; 150 } 151 case MediaSliderThumb: 152 wkDrawMediaUIPart(WKMediaUIPartTimelineSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 153 break; 154 case MediaVolumeSliderContainer: 155 wkDrawMediaUIPart(WKMediaUIPartVolumeSliderContainer, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 156 break; 157 case MediaVolumeSlider: 158 wkDrawMediaUIPart(WKMediaUIPartVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 159 break; 160 case MediaVolumeSliderThumb: 161 wkDrawMediaUIPart(WKMediaUIPartVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 162 break; 163 case MediaTimelineContainer: 164 wkDrawMediaUIPart(WKMediaUIPartBackground, themeStyle, paintInfo.context->platformContext(), r, determineState(o)); 165 break; 166 case MediaCurrentTimeDisplay: 167 ASSERT_NOT_REACHED(); 168 break; 169 case MediaTimeRemainingDisplay: 170 ASSERT_NOT_REACHED(); 171 break; 172 case MediaControlsPanel: 173 ASSERT_NOT_REACHED(); 174 break; 175 } 176 paintInfo.context->restore(); 177 178 return false; 179 } 180 181 #endif 182 183 IntPoint RenderMediaControls::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size) 184 { 185 static const int xOffset = -4; 186 static const int yOffset = 5; 187 188 float zoomLevel = muteButtonBox->style()->effectiveZoom(); 189 int y = yOffset * zoomLevel + muteButtonBox->offsetHeight() - size.height(); 190 FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true); 191 if (absPoint.y() < 0) 192 y = muteButtonBox->height(); 193 return IntPoint(xOffset * zoomLevel, y); 194 } 195 196 } 197 198 #endif 199