blob: 8395a9a87769a9628b6e7f1ae7086ce34d7bb4ff [file] [log] [blame]
/*
* Copyright (C) 2009, 2013 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if ENABLE(VIDEO)
#include "RenderMediaControls.h"
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLNames.h"
#include "PaintInfo.h"
#include "RenderTheme.h"
// FIXME: Unify more of the code for Mac and Win.
#if PLATFORM(WIN) && USE(CG)
#include <CoreGraphics/CoreGraphics.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
// The Windows version of WKSI defines these functions as capitalized, while the Mac version defines them as lower case.
// FIXME: Is this necessary anymore?
inline bool wkHitTestMediaUIPart(int part, const CGRect& bounds, const CGPoint& point)
{
WKHitTestMediaUIPart(part, bounds, point);
}
inline void wkMeasureMediaUIPart(int part, CGRect* bounds, CGSize* naturalSize)
{
WKMeasureMediaUIPart(part, bounds, naturalSize);
}
inline void wkDrawMediaUIPart(int part, CGContextRef context, const CGRect& rect, unsigned state)
{
WKDrawMediaUIPart(part, context, rect, state);
}
inline void wkDrawMediaSliderTrack(CGContextRef context, const CGRect& rect, float timeLoaded, float currentTime, float duration, unsigned state)
{
WKDrawMediaSliderTrack(context, rect, timeLoaded, currentTime, duration, state);
}
#endif
namespace WebCore {
#if PLATFORM(WIN) && USE(CG)
static WKMediaControllerThemeState determineState(RenderObject* o)
{
int result = 0;
RenderTheme* theme = o->theme();
if (!theme->isEnabled(o) || theme->isReadOnlyControl(o))
result |= WKMediaControllerFlagDisabled;
if (theme->isPressed(o))
result |= WKMediaControllerFlagPressed;
if (theme->isFocused(o))
result |= WKMediaControllerFlagFocused;
return static_cast<WKMediaControllerThemeState>(result);
}
// Utility to scale when the UI part are not scaled by wkDrawMediaUIPart
static FloatRect getUnzoomedRectAndAdjustCurrentContext(RenderObject* o, const PaintInfo& paintInfo, const IntRect &originalRect)
{
float zoomLevel = o->style().effectiveZoom();
FloatRect unzoomedRect(originalRect);
if (zoomLevel != 1.0f) {
unzoomedRect.setWidth(unzoomedRect.width() / zoomLevel);
unzoomedRect.setHeight(unzoomedRect.height() / zoomLevel);
paintInfo.context->translate(unzoomedRect.x(), unzoomedRect.y());
paintInfo.context->scale(FloatSize(zoomLevel, zoomLevel));
paintInfo.context->translate(-unzoomedRect.x(), -unzoomedRect.y());
}
return unzoomedRect;
}
static const int mediaSliderThumbWidth = 13;
static const int mediaSliderThumbHeight = 14;
void RenderMediaControls::adjustMediaSliderThumbSize(RenderStyle* style)
{
int part;
switch (style->appearance()) {
case MediaSliderThumbPart:
part = MediaSliderThumb;
break;
case MediaVolumeSliderThumbPart:
part = MediaVolumeSliderThumb;
break;
case MediaFullScreenVolumeSliderThumbPart:
part = MediaFullScreenVolumeSliderThumb;
break;
default:
return;
}
CGSize size;
wkMeasureMediaUIPart(part, 0, &size);
float zoomLevel = style->effectiveZoom();
style->setWidth(Length(static_cast<int>(size.width * zoomLevel), Fixed));
style->setHeight(Length(static_cast<int>(size.height * zoomLevel), Fixed));
}
bool RenderMediaControls::paintMediaControlsPart(MediaControlElementType part, RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
{
GraphicsContextStateSaver stateSaver(*paintInfo.context);
switch (part) {
case MediaEnterFullscreenButton:
case MediaExitFullscreenButton:
if (MediaControlFullscreenButtonElement* btn = static_cast<MediaControlFullscreenButtonElement*>(o->node())) {
bool enterButton = btn->displayType() == MediaEnterFullscreenButton;
wkDrawMediaUIPart(enterButton ? WKMediaUIPartFullscreenButton : WKMediaUIPartExitFullscreenButton, paintInfo.context->platformContext(), r, determineState(o));
}
break;
case MediaShowClosedCaptionsButton:
case MediaHideClosedCaptionsButton:
if (MediaControlToggleClosedCaptionsButtonElement* btn = static_cast<MediaControlToggleClosedCaptionsButtonElement*>(o->node())) {
bool captionsVisible = btn->displayType() == MediaHideClosedCaptionsButton;
wkDrawMediaUIPart(captionsVisible ? WKMediaUIPartHideClosedCaptionsButton : WKMediaUIPartShowClosedCaptionsButton, paintInfo.context->platformContext(), r, determineState(o));
}
break;
case MediaMuteButton:
case MediaUnMuteButton:
if (MediaControlMuteButtonElement* btn = static_cast<MediaControlMuteButtonElement*>(o->node())) {
bool audioEnabled = btn->displayType() == MediaMuteButton;
wkDrawMediaUIPart(audioEnabled ? WKMediaUIPartMuteButton : WKMediaUIPartUnMuteButton, paintInfo.context->platformContext(), r, determineState(o));
}
break;
case MediaPauseButton:
case MediaPlayButton:
if (MediaControlPlayButtonElement* btn = static_cast<MediaControlPlayButtonElement*>(o->node())) {
bool canPlay = btn->displayType() == MediaPlayButton;
wkDrawMediaUIPart(canPlay ? WKMediaUIPartPlayButton : WKMediaUIPartPauseButton, paintInfo.context->platformContext(), r, determineState(o));
}
break;
case MediaRewindButton:
wkDrawMediaUIPart(WKMediaUIPartRewindButton, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaReturnToRealtimeButton:
wkDrawMediaUIPart(WKMediaUIPartSeekToRealtimeButton, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaSeekBackButton:
wkDrawMediaUIPart(WKMediaUIPartSeekBackButton, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaSeekForwardButton:
wkDrawMediaUIPart(WKMediaUIPartSeekForwardButton, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaSlider: {
if (HTMLMediaElement* mediaElement = parentMediaElement(*o)) {
FloatRect unzoomedRect = getUnzoomedRectAndAdjustCurrentContext(o, paintInfo, r);
wkDrawMediaSliderTrack(paintInfo.context->platformContext(), unzoomedRect, mediaElement->percentLoaded() * mediaElement->duration(), mediaElement->currentTime(), mediaElement->duration(), determineState(o));
}
break;
}
case MediaSliderThumb:
wkDrawMediaUIPart(WKMediaUIPartTimelineSliderThumb, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaVolumeSliderContainer:
wkDrawMediaUIPart(WKMediaUIPartVolumeSliderContainer, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaVolumeSlider:
wkDrawMediaUIPart(WKMediaUIPartVolumeSlider, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaVolumeSliderThumb:
wkDrawMediaUIPart(WKMediaUIPartVolumeSliderThumb, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaFullScreenVolumeSlider:
wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSlider, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaFullScreenVolumeSliderThumb:
wkDrawMediaUIPart(WKMediaUIPartFullScreenVolumeSliderThumb, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaTimelineContainer:
wkDrawMediaUIPart(WKMediaUIPartBackground, paintInfo.context->platformContext(), r, determineState(o));
break;
case MediaCurrentTimeDisplay:
ASSERT_NOT_REACHED();
break;
case MediaTimeRemainingDisplay:
ASSERT_NOT_REACHED();
break;
case MediaControlsPanel:
ASSERT_NOT_REACHED();
case MediaTextTrackDisplayContainer:
case MediaTextTrackDisplay:
case MediaClosedCaptionsContainer:
case MediaClosedCaptionsTrackList:
ASSERT_NOT_REACHED();
break;
}
return false;
}
#endif
IntPoint RenderMediaControls::volumeSliderOffsetFromMuteButton(RenderBox* muteButtonBox, const IntSize& size)
{
static const int xOffset = -4;
static const int yOffset = 5;
float zoomLevel = muteButtonBox->style().effectiveZoom();
int y = yOffset * zoomLevel + muteButtonBox->pixelSnappedOffsetHeight() - size.height();
FloatPoint absPoint = muteButtonBox->localToAbsolute(FloatPoint(muteButtonBox->pixelSnappedOffsetLeft(), y), IsFixed | UseTransforms);
if (absPoint.y() < 0)
y = muteButtonBox->pixelSnappedHeight();
return IntPoint(xOffset * zoomLevel, y);
}
}
#endif