WebCore/rendering/RenderMediaControlsChromium.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebCore/rendering/RenderMediaControlsChromium.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2009 Apple Inc.
+ * Copyright (C) 2009 Google 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"
+#include "RenderMediaControlsChromium.h"
+
+#include "Gradient.h"
+#include "GraphicsContext.h"
+#include "HTMLMediaElement.h"
+#include "HTMLNames.h"
+
+namespace WebCore {
+
+#if ENABLE(VIDEO)
+
+typedef WTF::HashMap<const char*, Image*> MediaControlImageMap;
+static MediaControlImageMap* gMediaControlImageMap = 0;
+
+static Image* platformResource(const char* name)
+{
+    if (!gMediaControlImageMap)
+        gMediaControlImageMap = new MediaControlImageMap();
+    if (Image* image = gMediaControlImageMap->get(name))
+        return image;
+    if (Image* image = Image::loadPlatformResource(name).releaseRef()) {
+        gMediaControlImageMap->set(name, image);
+        return image;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+static bool hasSource(const HTMLMediaElement* mediaElement)
+{
+    return mediaElement->networkState() != HTMLMediaElement::NETWORK_EMPTY
+        && mediaElement->networkState() != HTMLMediaElement::NETWORK_NO_SOURCE;
+}
+
+static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image)
+{
+    IntRect imageRect = image->rect();
+    context->drawImage(image, DeviceColorSpace, rect);
+    return true;
+}
+
+static bool paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+      return false;
+
+    static Image* soundFull = platformResource("mediaSoundFull");
+    static Image* soundNone = platformResource("mediaSoundNone");
+    static Image* soundDisabled = platformResource("mediaSoundDisabled");
+
+    if (!hasSource(mediaElement) || !mediaElement->hasAudio())
+        return paintMediaButton(paintInfo.context, rect, soundDisabled);
+
+    return paintMediaButton(paintInfo.context, rect, mediaElement->muted() ? soundNone: soundFull);
+}
+
+static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    static Image* mediaPlay = platformResource("mediaPlay");
+    static Image* mediaPause = platformResource("mediaPause");
+    static Image* mediaPlayDisabled = platformResource("mediaPlayDisabled");
+
+    if (!hasSource(mediaElement))
+        return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled);
+
+    return paintMediaButton(paintInfo.context, rect, mediaElement->paused() ? mediaPlay : mediaPause);
+}
+
+static Image* getMediaSliderThumb()
+{
+    static Image* mediaSliderThumb = platformResource("mediaSliderThumb");
+    return mediaSliderThumb;
+}
+
+static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    RenderStyle* style = object->style();
+    GraphicsContext* context = paintInfo.context;
+
+    // Draw the border of the time bar.
+    // FIXME: this should be a rounded rect but need to fix GraphicsContextSkia first.
+    // https://bugs.webkit.org/show_bug.cgi?id=30143
+    context->save();
+    context->setShouldAntialias(true);
+    context->setStrokeStyle(SolidStroke);
+    context->setStrokeColor(style->visitedDependentColor(CSSPropertyBorderLeftColor), DeviceColorSpace);
+    context->setStrokeThickness(style->borderLeftWidth());
+    context->setFillColor(style->visitedDependentColor(CSSPropertyBackgroundColor), DeviceColorSpace);
+    context->drawRect(rect);
+    context->restore();
+
+    // Draw the buffered ranges.
+    // FIXME: Draw multiple ranges if there are multiple buffered ranges.
+    IntRect bufferedRect = rect;
+    bufferedRect.inflate(-style->borderLeftWidth());
+
+    double bufferedWidth = 0.0;
+    if (mediaElement->percentLoaded() > 0.0) {
+        // Account for the width of the slider thumb.
+        Image* mediaSliderThumb = getMediaSliderThumb();
+        double thumbWidth = mediaSliderThumb->width() / 2.0 + 1.0;
+        double rectWidth = bufferedRect.width() - thumbWidth;
+        if (rectWidth < 0.0)
+            rectWidth = 0.0;
+        bufferedWidth = rectWidth * mediaElement->percentLoaded() + thumbWidth;
+    }
+    bufferedRect.setWidth(bufferedWidth);
+
+    // Don't bother drawing an empty area.
+    if (!bufferedRect.isEmpty()) {
+        IntPoint sliderTopLeft = bufferedRect.location();
+        IntPoint sliderTopRight = sliderTopLeft;
+        sliderTopRight.move(0, bufferedRect.height());
+
+        RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderTopRight);
+        Color startColor = object->style()->visitedDependentColor(CSSPropertyColor);
+        gradient->addColorStop(0.0, startColor);
+        gradient->addColorStop(1.0, Color(startColor.red() / 2, startColor.green() / 2, startColor.blue() / 2, startColor.alpha()));
+
+        context->save();
+        context->setStrokeStyle(NoStroke);
+        context->setFillGradient(gradient);
+        context->fillRect(bufferedRect);
+        context->restore();
+    }
+
+    return true;
+}
+
+static bool paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    if (!object->parent()->isSlider())
+        return false;
+
+    HTMLMediaElement* mediaElement = toParentMediaElement(object->parent());
+    if (!mediaElement)
+        return false;
+
+    if (!hasSource(mediaElement))
+        return true;
+
+    Image* mediaSliderThumb = getMediaSliderThumb();
+    return paintMediaButton(paintInfo.context, rect, mediaSliderThumb);
+}
+
+static bool paintMediaVolumeSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    GraphicsContext* context = paintInfo.context;
+    Color originalColor = context->strokeColor();
+    if (originalColor != Color::white)
+        context->setStrokeColor(Color::white, DeviceColorSpace);
+
+    int x = rect.x() + rect.width() / 2;
+    context->drawLine(IntPoint(x, rect.y()),  IntPoint(x, rect.y() + rect.height()));
+
+    if (originalColor != Color::white)
+        context->setStrokeColor(originalColor, DeviceColorSpace);
+    return true;
+}
+
+static bool paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    if (!object->parent()->isSlider())
+        return false;
+
+    static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb");
+    return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb);
+}
+
+static bool paintMediaTimelineContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    if (!rect.isEmpty()) {
+        GraphicsContext* context = paintInfo.context;
+        Color originalColor = context->strokeColor();
+        float originalThickness = context->strokeThickness();
+        StrokeStyle originalStyle = context->strokeStyle();
+
+        context->setStrokeStyle(SolidStroke);
+
+        // Draw the left border using CSS defined width and color.
+        context->setStrokeThickness(object->style()->borderLeftWidth());
+        context->setStrokeColor(object->style()->visitedDependentColor(CSSPropertyBorderLeftColor).rgb(), DeviceColorSpace);
+        context->drawLine(IntPoint(rect.x() + 1, rect.y()),
+                          IntPoint(rect.x() + 1, rect.y() + rect.height()));
+
+        // Draw the right border using CSS defined width and color.
+        context->setStrokeThickness(object->style()->borderRightWidth());
+        context->setStrokeColor(object->style()->visitedDependentColor(CSSPropertyBorderRightColor).rgb(), DeviceColorSpace);
+        context->drawLine(IntPoint(rect.x() + rect.width() - 1, rect.y()),
+                          IntPoint(rect.x() + rect.width() - 1, rect.y() + rect.height()));
+
+        context->setStrokeColor(originalColor, DeviceColorSpace);
+        context->setStrokeThickness(originalThickness);
+        context->setStrokeStyle(originalStyle);
+    }
+    return true;
+}
+
+bool RenderMediaControlsChromium::shouldRenderMediaControlPart(ControlPart part, Element* e)
+{
+    UNUSED_PARAM(e);
+
+    switch (part) {
+    case MediaMuteButtonPart:
+    case MediaPlayButtonPart:
+    case MediaSliderPart:
+    case MediaSliderThumbPart:
+    case MediaVolumeSliderContainerPart:
+    case MediaVolumeSliderPart:
+    case MediaVolumeSliderThumbPart:
+    case MediaControlsBackgroundPart:
+    case MediaCurrentTimePart:
+    case MediaTimeRemainingPart:
+        return true;
+    default:
+        ;
+    }
+    return false;
+}
+
+bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    switch (part) {
+    case MediaMuteButton:
+    case MediaUnMuteButton:
+        return paintMediaMuteButton(object, paintInfo, rect);
+    case MediaPauseButton:
+    case MediaPlayButton:
+        return paintMediaPlayButton(object, paintInfo, rect);
+    case MediaSlider:
+        return paintMediaSlider(object, paintInfo, rect);
+    case MediaSliderThumb:
+        return paintMediaSliderThumb(object, paintInfo, rect);
+    case MediaVolumeSlider:
+        return paintMediaVolumeSlider(object, paintInfo, rect);
+    case MediaVolumeSliderThumb:
+        return paintMediaVolumeSliderThumb(object, paintInfo, rect);
+    case MediaTimelineContainer:
+        return paintMediaTimelineContainer(object, paintInfo, rect);
+    case MediaVolumeSliderMuteButton:
+    case MediaFullscreenButton:
+    case MediaSeekBackButton:
+    case MediaSeekForwardButton:
+    case MediaVolumeSliderContainer:
+    case MediaCurrentTimeDisplay:
+    case MediaTimeRemainingDisplay:
+    case MediaControlsPanel:
+    case MediaRewindButton:
+    case MediaReturnToRealtimeButton:
+    case MediaStatusDisplay:
+    case MediaShowClosedCaptionsButton:
+    case MediaHideClosedCaptionsButton:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    return false;
+}
+
+void RenderMediaControlsChromium::adjustMediaSliderThumbSize(RenderObject* object)
+{
+    static Image* mediaSliderThumb = platformResource("mediaSliderThumb");
+    static Image* mediaVolumeSliderThumb = platformResource("mediaVolumeSliderThumb");
+
+    Image* thumbImage = 0;
+    if (object->style()->appearance() == MediaSliderThumbPart)
+        thumbImage = mediaSliderThumb;
+    else if (object->style()->appearance() == MediaVolumeSliderThumbPart)
+        thumbImage = mediaVolumeSliderThumb;
+
+    float zoomLevel = object->style()->effectiveZoom();
+    if (thumbImage) {
+        object->style()->setWidth(Length(static_cast<int>(thumbImage->width() * zoomLevel), Fixed));
+        object->style()->setHeight(Length(static_cast<int>(thumbImage->height() * zoomLevel), Fixed));
+    }
+}
+
+#endif  // #if ENABLE(VIDEO)
+
+} // namespace WebCore