92aa2abd01727e5c69c4388dbd591d2f49feacda
[WebKit-https.git] / Source / WebCore / rendering / RenderMediaControls.cpp
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(RenderStyle* style)
92 {
93     ControlPart part = style->appearance();
94     if (part != MediaSliderThumbPart && part != MediaVolumeSliderThumbPart)
95         return;
96
97     CGSize size;
98     wkMeasureMediaUIPart(part == MediaSliderThumbPart ? MediaSliderThumb : MediaVolumeSliderThumb, WKMediaControllerThemeQuickTime, 0, &size);
99
100     float zoomLevel = style->effectiveZoom();
101     style->setWidth(Length(static_cast<int>(size.width * zoomLevel), Fixed));
102     style->setHeight(Length(static_cast<int>(size.height * zoomLevel), Fixed));
103 }
104
105 bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
106 {
107     static const int themeStyle = WKMediaControllerThemeQuickTime;
108     GraphicsContextStateSaver stateSaver(*paintInfo.context);
109
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 MediaReturnToRealtimeButton:
139             wkDrawMediaUIPart(WKMediaUIPartSeekToRealtimeButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
140             break;
141         case MediaSeekBackButton:
142             wkDrawMediaUIPart(WKMediaUIPartSeekBackButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
143             break;
144         case MediaSeekForwardButton:
145             wkDrawMediaUIPart(WKMediaUIPartSeekForwardButton, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
146             break;
147         case MediaSlider: {
148             if (HTMLMediaElement* mediaElement = toParentMediaElement(o)) {
149                 FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
150                 wkDrawMediaSliderTrack(themeStyle, paintInfo.context->platformContext(), unzoomedRect, mediaElement->percentLoaded() * mediaElement->duration(), mediaElement->currentTime(), mediaElement->duration(), determineState(o));
151             }
152             break;
153         }
154         case MediaSliderThumb:
155             wkDrawMediaUIPart(WKMediaUIPartTimelineSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
156             break;
157         case MediaVolumeSliderContainer:
158             wkDrawMediaUIPart(WKMediaUIPartVolumeSliderContainer, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
159             break;
160         case MediaVolumeSlider:
161             wkDrawMediaUIPart(WKMediaUIPartVolumeSlider, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
162             break;
163         case MediaVolumeSliderThumb:
164             wkDrawMediaUIPart(WKMediaUIPartVolumeSliderThumb, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
165             break;
166         case MediaTimelineContainer:
167             wkDrawMediaUIPart(WKMediaUIPartBackground, themeStyle, paintInfo.context->platformContext(), r, determineState(o));
168             break;
169         case MediaCurrentTimeDisplay:
170             ASSERT_NOT_REACHED();
171             break;
172         case MediaTimeRemainingDisplay:
173             ASSERT_NOT_REACHED();
174             break;
175         case MediaControlsPanel:
176             ASSERT_NOT_REACHED();
177             break;
178     }
179
180     return false;
181 }
182
183 #endif
184
185 IntPoint RenderMediaControls::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size)
186 {
187     static const int xOffset = -4;
188     static const int yOffset = 5;
189
190     float zoomLevel = muteButtonBox->style()->effectiveZoom();
191     int y = yOffset * zoomLevel + muteButtonBox->offsetHeight() - size.height();
192     FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->offsetLeft(), y), true, true);
193     if (absPoint.y() < 0)
194         y = muteButtonBox->height();
195     return IntPoint(xOffset * zoomLevel, y);
196 }
197
198 }
199
200 #endif