| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2009 Apple Inc. | |
| 3 * Copyright (C) 2009 Google Inc. | |
| 4 * All rights reserved. | |
| 5 * | |
| 6 * Redistribution and use in source and binary forms, with or without | |
| 7 * modification, are permitted provided that the following conditions | |
| 8 * are met: | |
| 9 * 1. Redistributions of source code must retain the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer. | |
| 11 * 2. Redistributions in binary form must reproduce the above copyright | |
| 12 * notice, this list of conditions and the following disclaimer in the | |
| 13 * documentation and/or other materials provided with the distribution. | |
| 14 * | |
| 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
| 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 26 */ | |
| 27 | |
| 28 #include "config.h" | |
| 29 #include "core/layout/LayoutMediaControls.h" | |
| 30 | |
| 31 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | |
| 32 #include "core/html/HTMLMediaElement.h" | |
| 33 #include "core/html/TimeRanges.h" | |
| 34 #include "core/paint/PaintInfo.h" | |
| 35 #include "platform/graphics/Gradient.h" | |
| 36 #include "platform/graphics/GraphicsContext.h" | |
| 37 | |
| 38 namespace blink { | |
| 39 | |
| 40 typedef WTF::HashMap<const char*, Image*> MediaControlImageMap; | |
| 41 static MediaControlImageMap* gMediaControlImageMap = 0; | |
| 42 static double kCurrentTimeBufferedDelta = 1.0; | |
| 43 | |
| 44 static Image* platformResource(const char* name) | |
| 45 { | |
| 46 if (!gMediaControlImageMap) | |
| 47 gMediaControlImageMap = new MediaControlImageMap(); | |
| 48 if (Image* image = gMediaControlImageMap->get(name)) | |
| 49 return image; | |
| 50 if (Image* image = Image::loadPlatformResource(name).leakRef()) { | |
| 51 gMediaControlImageMap->set(name, image); | |
| 52 return image; | |
| 53 } | |
| 54 ASSERT_NOT_REACHED(); | |
| 55 return 0; | |
| 56 } | |
| 57 | |
| 58 static bool hasSource(const HTMLMediaElement* mediaElement) | |
| 59 { | |
| 60 return mediaElement->networkState() != HTMLMediaElement::NETWORK_EMPTY | |
| 61 && mediaElement->networkState() != HTMLMediaElement::NETWORK_NO_SOURCE; | |
| 62 } | |
| 63 | |
| 64 static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Imag
e* image) | |
| 65 { | |
| 66 context->drawImage(image, rect); | |
| 67 return true; | |
| 68 } | |
| 69 | |
| 70 static bool paintMediaMuteButton(LayoutObject* object, const PaintInfo& paintInf
o, const IntRect& rect) | |
| 71 { | |
| 72 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 73 if (!mediaElement) | |
| 74 return false; | |
| 75 | |
| 76 static Image* soundLevel3 = platformResource("mediaplayerSoundLevel3"); | |
| 77 static Image* soundLevel2 = platformResource("mediaplayerSoundLevel2"); | |
| 78 static Image* soundLevel1 = platformResource("mediaplayerSoundLevel1"); | |
| 79 static Image* soundLevel0 = platformResource("mediaplayerSoundLevel0"); | |
| 80 static Image* soundDisabled = platformResource("mediaplayerSoundDisabled"); | |
| 81 | |
| 82 if (!hasSource(mediaElement) || !mediaElement->hasAudio()) | |
| 83 return paintMediaButton(paintInfo.context, rect, soundDisabled); | |
| 84 | |
| 85 if (mediaElement->muted() || mediaElement->volume() <= 0) | |
| 86 return paintMediaButton(paintInfo.context, rect, soundLevel0); | |
| 87 | |
| 88 if (mediaElement->volume() <= 0.33) | |
| 89 return paintMediaButton(paintInfo.context, rect, soundLevel1); | |
| 90 | |
| 91 if (mediaElement->volume() <= 0.66) | |
| 92 return paintMediaButton(paintInfo.context, rect, soundLevel2); | |
| 93 | |
| 94 return paintMediaButton(paintInfo.context, rect, soundLevel3); | |
| 95 } | |
| 96 | |
| 97 static bool paintMediaPlayButton(LayoutObject* object, const PaintInfo& paintInf
o, const IntRect& rect) | |
| 98 { | |
| 99 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 100 if (!mediaElement) | |
| 101 return false; | |
| 102 | |
| 103 static Image* mediaPlay = platformResource("mediaplayerPlay"); | |
| 104 static Image* mediaPause = platformResource("mediaplayerPause"); | |
| 105 static Image* mediaPlayDisabled = platformResource("mediaplayerPlayDisabled"
); | |
| 106 | |
| 107 if (!hasSource(mediaElement)) | |
| 108 return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled); | |
| 109 | |
| 110 Image * image = !object->node()->isMediaControlElement() || mediaControlElem
entType(object->node()) == MediaPlayButton ? mediaPlay : mediaPause; | |
| 111 return paintMediaButton(paintInfo.context, rect, image); | |
| 112 } | |
| 113 | |
| 114 static bool paintMediaOverlayPlayButton(LayoutObject* object, const PaintInfo& p
aintInfo, const IntRect& rect) | |
| 115 { | |
| 116 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 117 if (!mediaElement) | |
| 118 return false; | |
| 119 | |
| 120 if (!hasSource(mediaElement) || !mediaElement->togglePlayStateWillPlay()) | |
| 121 return false; | |
| 122 | |
| 123 static Image* mediaOverlayPlay = platformResource("mediaplayerOverlayPlay"); | |
| 124 return paintMediaButton(paintInfo.context, rect, mediaOverlayPlay); | |
| 125 } | |
| 126 | |
| 127 static Image* getMediaSliderThumb() | |
| 128 { | |
| 129 static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb"); | |
| 130 return mediaSliderThumb; | |
| 131 } | |
| 132 | |
| 133 static void paintRoundedSliderBackground(const IntRect& rect, const ComputedStyl
e&, GraphicsContext* context) | |
| 134 { | |
| 135 int borderRadius = rect.height() / 2; | |
| 136 IntSize radii(borderRadius, borderRadius); | |
| 137 Color sliderBackgroundColor = Color(11, 11, 11); | |
| 138 context->fillRoundedRect(FloatRoundedRect(rect, radii, radii, radii, radii),
sliderBackgroundColor); | |
| 139 } | |
| 140 | |
| 141 static void paintSliderRangeHighlight(const IntRect& rect, const ComputedStyle&
style, GraphicsContext* context, int startPosition, int endPosition, Color start
Color, Color endColor) | |
| 142 { | |
| 143 // Calculate border radius; need to avoid being smaller than half the slider
height | |
| 144 // because of https://bugs.webkit.org/show_bug.cgi?id=30143. | |
| 145 int borderRadius = rect.height() / 2; | |
| 146 IntSize radii(borderRadius, borderRadius); | |
| 147 | |
| 148 // Calculate highlight rectangle and edge dimensions. | |
| 149 int startOffset = startPosition; | |
| 150 int endOffset = rect.width() - endPosition; | |
| 151 int rangeWidth = endPosition - startPosition; | |
| 152 | |
| 153 if (rangeWidth <= 0) | |
| 154 return; | |
| 155 | |
| 156 // Make sure the range width is bigger than border radius at the edges to re
tain rounded corners. | |
| 157 if (startOffset < borderRadius && rangeWidth < borderRadius) | |
| 158 rangeWidth = borderRadius; | |
| 159 if (endOffset < borderRadius && rangeWidth < borderRadius) | |
| 160 rangeWidth = borderRadius; | |
| 161 | |
| 162 // Set rectangle to highlight range. | |
| 163 IntRect highlightRect = rect; | |
| 164 highlightRect.move(startOffset, 0); | |
| 165 highlightRect.setWidth(rangeWidth); | |
| 166 | |
| 167 // Don't bother drawing an empty area. | |
| 168 if (highlightRect.isEmpty()) | |
| 169 return; | |
| 170 | |
| 171 // Calculate white-grey gradient. | |
| 172 IntPoint sliderTopLeft = highlightRect.location(); | |
| 173 IntPoint sliderBottomLeft = sliderTopLeft; | |
| 174 sliderBottomLeft.move(0, highlightRect.height()); | |
| 175 RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft
); | |
| 176 gradient->addColorStop(0.0, startColor); | |
| 177 gradient->addColorStop(1.0, endColor); | |
| 178 | |
| 179 // Fill highlight rectangle with gradient, potentially rounded if on left or
right edge. | |
| 180 context->save(); | |
| 181 context->setFillGradient(gradient); | |
| 182 | |
| 183 if (startOffset < borderRadius && endOffset < borderRadius) | |
| 184 context->fillRoundedRect(FloatRoundedRect(highlightRect, radii, radii, r
adii, radii), startColor); | |
| 185 else if (startOffset < borderRadius) | |
| 186 context->fillRoundedRect(FloatRoundedRect(highlightRect, radii, IntSize(
0, 0), radii, IntSize(0, 0)), startColor); | |
| 187 else if (endOffset < borderRadius) | |
| 188 context->fillRoundedRect(FloatRoundedRect(highlightRect, IntSize(0, 0),
radii, IntSize(0, 0), radii), startColor); | |
| 189 else | |
| 190 context->fillRect(highlightRect); | |
| 191 | |
| 192 context->restore(); | |
| 193 } | |
| 194 | |
| 195 const int mediaSliderThumbWidth = 32; | |
| 196 | |
| 197 static bool paintMediaSlider(LayoutObject* object, const PaintInfo& paintInfo, c
onst IntRect& rect) | |
| 198 { | |
| 199 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 200 if (!mediaElement) | |
| 201 return false; | |
| 202 | |
| 203 const ComputedStyle& style = object->styleRef(); | |
| 204 GraphicsContext* context = paintInfo.context; | |
| 205 | |
| 206 paintRoundedSliderBackground(rect, style, context); | |
| 207 | |
| 208 // Draw the buffered range. Since the element may have multiple buffered ran
ges and it'd be | |
| 209 // distracting/'busy' to show all of them, show only the buffered range cont
aining the current play head. | |
| 210 RefPtrWillBeRawPtr<TimeRanges> bufferedTimeRanges = mediaElement->buffered()
; | |
| 211 float duration = mediaElement->duration(); | |
| 212 float currentTime = mediaElement->currentTime(); | |
| 213 if (std::isnan(duration) || std::isinf(duration) || !duration || std::isnan(
currentTime)) | |
| 214 return true; | |
| 215 | |
| 216 for (unsigned i = 0; i < bufferedTimeRanges->length(); ++i) { | |
| 217 float start = bufferedTimeRanges->start(i, ASSERT_NO_EXCEPTION); | |
| 218 float end = bufferedTimeRanges->end(i, ASSERT_NO_EXCEPTION); | |
| 219 // The delta is there to avoid corner cases when buffered | |
| 220 // ranges is out of sync with current time because of | |
| 221 // asynchronous media pipeline and current time caching in | |
| 222 // HTMLMediaElement. | |
| 223 // This is related to https://www.w3.org/Bugs/Public/show_bug.cgi?id=281
25 | |
| 224 // FIXME: Remove this workaround when WebMediaPlayer | |
| 225 // has an asynchronous pause interface. | |
| 226 if (std::isnan(start) || std::isnan(end) | |
| 227 || start > currentTime + kCurrentTimeBufferedDelta || end < currentT
ime) | |
| 228 continue; | |
| 229 int startPosition = int(start * rect.width() / duration); | |
| 230 int currentPosition = int(currentTime * rect.width() / duration); | |
| 231 int endPosition = int(end * rect.width() / duration); | |
| 232 | |
| 233 // Add half the thumb width proportionally adjusted to the current paint
ing position. | |
| 234 int thumbCenter = mediaSliderThumbWidth / 2; | |
| 235 int addWidth = thumbCenter * (1.0 - 2.0 * currentPosition / rect.width()
); | |
| 236 currentPosition += addWidth; | |
| 237 | |
| 238 // Draw white-ish highlight before current time. | |
| 239 Color startColor = Color(195, 195, 195); | |
| 240 Color endColor = Color(217, 217, 217); | |
| 241 if (currentPosition > startPosition) | |
| 242 paintSliderRangeHighlight(rect, style, context, startPosition, curre
ntPosition, startColor, endColor); | |
| 243 | |
| 244 // Draw grey-ish highlight after current time. | |
| 245 startColor = Color(60, 60, 60); | |
| 246 endColor = Color(76, 76, 76); | |
| 247 | |
| 248 if (endPosition > currentPosition) | |
| 249 paintSliderRangeHighlight(rect, style, context, currentPosition, end
Position, startColor, endColor); | |
| 250 | |
| 251 return true; | |
| 252 } | |
| 253 | |
| 254 return true; | |
| 255 } | |
| 256 | |
| 257 static bool paintMediaSliderThumb(LayoutObject* object, const PaintInfo& paintIn
fo, const IntRect& rect) | |
| 258 { | |
| 259 if (!object->node()) | |
| 260 return false; | |
| 261 | |
| 262 HTMLMediaElement* mediaElement = toParentMediaElement(object->node()->shadow
Host()); | |
| 263 if (!mediaElement) | |
| 264 return false; | |
| 265 | |
| 266 if (!hasSource(mediaElement)) | |
| 267 return true; | |
| 268 | |
| 269 Image* mediaSliderThumb = getMediaSliderThumb(); | |
| 270 return paintMediaButton(paintInfo.context, rect, mediaSliderThumb); | |
| 271 } | |
| 272 | |
| 273 const int mediaVolumeSliderThumbWidth = 24; | |
| 274 | |
| 275 static bool paintMediaVolumeSlider(LayoutObject* object, const PaintInfo& paintI
nfo, const IntRect& rect) | |
| 276 { | |
| 277 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 278 if (!mediaElement) | |
| 279 return false; | |
| 280 | |
| 281 GraphicsContext* context = paintInfo.context; | |
| 282 const ComputedStyle& style = object->styleRef(); | |
| 283 | |
| 284 paintRoundedSliderBackground(rect, style, context); | |
| 285 | |
| 286 // Calculate volume position for white background rectangle. | |
| 287 float volume = mediaElement->volume(); | |
| 288 if (std::isnan(volume) || volume < 0) | |
| 289 return true; | |
| 290 if (volume > 1) | |
| 291 volume = 1; | |
| 292 if (!hasSource(mediaElement) || !mediaElement->hasAudio() || mediaElement->m
uted()) | |
| 293 volume = 0; | |
| 294 | |
| 295 // Calculate the position relative to the center of the thumb. | |
| 296 float fillWidth = 0; | |
| 297 if (volume > 0) { | |
| 298 float thumbCenter = mediaVolumeSliderThumbWidth / 2; | |
| 299 float zoomLevel = style.effectiveZoom(); | |
| 300 float positionWidth = volume * (rect.width() - (zoomLevel * thumbCenter)
); | |
| 301 fillWidth = positionWidth + (zoomLevel * thumbCenter / 2); | |
| 302 } | |
| 303 | |
| 304 Color startColor = Color(195, 195, 195); | |
| 305 Color endColor = Color(217, 217, 217); | |
| 306 | |
| 307 paintSliderRangeHighlight(rect, style, context, 0.0, fillWidth, startColor,
endColor); | |
| 308 | |
| 309 return true; | |
| 310 } | |
| 311 | |
| 312 static bool paintMediaVolumeSliderThumb(LayoutObject* object, const PaintInfo& p
aintInfo, const IntRect& rect) | |
| 313 { | |
| 314 if (!object->node()) | |
| 315 return false; | |
| 316 | |
| 317 HTMLMediaElement* mediaElement = toParentMediaElement(object->node()->shadow
Host()); | |
| 318 if (!mediaElement) | |
| 319 return false; | |
| 320 | |
| 321 if (!hasSource(mediaElement) || !mediaElement->hasAudio()) | |
| 322 return true; | |
| 323 | |
| 324 static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSl
iderThumb"); | |
| 325 return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb); | |
| 326 } | |
| 327 | |
| 328 static bool paintMediaFullscreenButton(LayoutObject* object, const PaintInfo& pa
intInfo, const IntRect& rect) | |
| 329 { | |
| 330 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 331 if (!mediaElement) | |
| 332 return false; | |
| 333 | |
| 334 static Image* mediaFullscreenButton = platformResource("mediaplayerFullscree
n"); | |
| 335 return paintMediaButton(paintInfo.context, rect, mediaFullscreenButton); | |
| 336 } | |
| 337 | |
| 338 static bool paintMediaToggleClosedCaptionsButton(LayoutObject* object, const Pai
ntInfo& paintInfo, const IntRect& rect) | |
| 339 { | |
| 340 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 341 if (!mediaElement) | |
| 342 return false; | |
| 343 | |
| 344 static Image* mediaClosedCaptionButton = platformResource("mediaplayerClosed
Caption"); | |
| 345 static Image* mediaClosedCaptionButtonDisabled = platformResource("mediaplay
erClosedCaptionDisabled"); | |
| 346 | |
| 347 if (mediaElement->closedCaptionsVisible()) | |
| 348 return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButto
n); | |
| 349 | |
| 350 return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButtonDis
abled); | |
| 351 } | |
| 352 static bool paintMediaCastButton(LayoutObject* object, const PaintInfo& paintInf
o, const IntRect& rect) | |
| 353 { | |
| 354 HTMLMediaElement* mediaElement = toParentMediaElement(object); | |
| 355 if (!mediaElement) | |
| 356 return false; | |
| 357 | |
| 358 static Image* mediaCastOn = platformResource("mediaplayerCastOn"); | |
| 359 static Image* mediaCastOff = platformResource("mediaplayerCastOff"); | |
| 360 // To ensure that the overlaid cast button is visible when overlaid on pale
videos we use a | |
| 361 // different version of it for the overlaid case with a semi-opaque backgrou
nd. | |
| 362 static Image* mediaOverlayCastOff = platformResource("mediaplayerOverlayCast
Off"); | |
| 363 | |
| 364 switch (mediaControlElementType(object->node())) { | |
| 365 case MediaCastOnButton: | |
| 366 case MediaOverlayCastOnButton: | |
| 367 return paintMediaButton(paintInfo.context, rect, mediaCastOn); | |
| 368 case MediaCastOffButton: | |
| 369 return paintMediaButton(paintInfo.context, rect, mediaCastOff); | |
| 370 case MediaOverlayCastOffButton: | |
| 371 return paintMediaButton(paintInfo.context, rect, mediaOverlayCastOff); | |
| 372 default: | |
| 373 ASSERT_NOT_REACHED(); | |
| 374 return false; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 bool LayoutMediaControls::paintMediaControlsPart(MediaControlElementType part, L
ayoutObject* object, const PaintInfo& paintInfo, const IntRect& rect) | |
| 379 { | |
| 380 switch (part) { | |
| 381 case MediaMuteButton: | |
| 382 case MediaUnMuteButton: | |
| 383 return paintMediaMuteButton(object, paintInfo, rect); | |
| 384 case MediaPauseButton: | |
| 385 case MediaPlayButton: | |
| 386 return paintMediaPlayButton(object, paintInfo, rect); | |
| 387 case MediaShowClosedCaptionsButton: | |
| 388 return paintMediaToggleClosedCaptionsButton(object, paintInfo, rect); | |
| 389 case MediaSlider: | |
| 390 return paintMediaSlider(object, paintInfo, rect); | |
| 391 case MediaSliderThumb: | |
| 392 return paintMediaSliderThumb(object, paintInfo, rect); | |
| 393 case MediaVolumeSlider: | |
| 394 return paintMediaVolumeSlider(object, paintInfo, rect); | |
| 395 case MediaVolumeSliderThumb: | |
| 396 return paintMediaVolumeSliderThumb(object, paintInfo, rect); | |
| 397 case MediaEnterFullscreenButton: | |
| 398 case MediaExitFullscreenButton: | |
| 399 return paintMediaFullscreenButton(object, paintInfo, rect); | |
| 400 case MediaOverlayPlayButton: | |
| 401 return paintMediaOverlayPlayButton(object, paintInfo, rect); | |
| 402 case MediaCastOffButton: | |
| 403 case MediaCastOnButton: | |
| 404 case MediaOverlayCastOffButton: | |
| 405 case MediaOverlayCastOnButton: | |
| 406 return paintMediaCastButton(object, paintInfo, rect); | |
| 407 case MediaVolumeSliderContainer: | |
| 408 case MediaTimelineContainer: | |
| 409 case MediaCurrentTimeDisplay: | |
| 410 case MediaTimeRemainingDisplay: | |
| 411 case MediaControlsPanel: | |
| 412 case MediaHideClosedCaptionsButton: | |
| 413 case MediaFullScreenVolumeSlider: | |
| 414 case MediaFullScreenVolumeSliderThumb: | |
| 415 ASSERT_NOT_REACHED(); | |
| 416 break; | |
| 417 } | |
| 418 return false; | |
| 419 } | |
| 420 | |
| 421 const int mediaSliderThumbHeight = 24; | |
| 422 const int mediaVolumeSliderThumbHeight = 24; | |
| 423 | |
| 424 void LayoutMediaControls::adjustMediaSliderThumbSize(ComputedStyle& style) | |
| 425 { | |
| 426 static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb"); | |
| 427 static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSl
iderThumb"); | |
| 428 int width = 0; | |
| 429 int height = 0; | |
| 430 | |
| 431 Image* thumbImage = 0; | |
| 432 if (style.appearance() == MediaSliderThumbPart) { | |
| 433 thumbImage = mediaSliderThumb; | |
| 434 width = mediaSliderThumbWidth; | |
| 435 height = mediaSliderThumbHeight; | |
| 436 } else if (style.appearance() == MediaVolumeSliderThumbPart) { | |
| 437 thumbImage = mediaVolumeSliderThumb; | |
| 438 width = mediaVolumeSliderThumbWidth; | |
| 439 height = mediaVolumeSliderThumbHeight; | |
| 440 } | |
| 441 | |
| 442 float zoomLevel = style.effectiveZoom(); | |
| 443 if (thumbImage) { | |
| 444 style.setWidth(Length(static_cast<int>(width * zoomLevel), Fixed)); | |
| 445 style.setHeight(Length(static_cast<int>(height * zoomLevel), Fixed)); | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 static String formatChromiumMediaControlsTime(float time, float duration) | |
| 450 { | |
| 451 if (!std::isfinite(time)) | |
| 452 time = 0; | |
| 453 if (!std::isfinite(duration)) | |
| 454 duration = 0; | |
| 455 int seconds = static_cast<int>(fabsf(time)); | |
| 456 int hours = seconds / (60 * 60); | |
| 457 int minutes = (seconds / 60) % 60; | |
| 458 seconds %= 60; | |
| 459 | |
| 460 // duration defines the format of how the time is rendered | |
| 461 int durationSecs = static_cast<int>(fabsf(duration)); | |
| 462 int durationHours = durationSecs / (60 * 60); | |
| 463 int durationMins = (durationSecs / 60) % 60; | |
| 464 | |
| 465 if (durationHours || hours) | |
| 466 return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours,
minutes, seconds); | |
| 467 if (durationMins > 9) | |
| 468 return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, sec
onds); | |
| 469 | |
| 470 return String::format("%s%01d:%02d", (time < 0 ? "-" : ""), minutes, seconds
); | |
| 471 } | |
| 472 | |
| 473 String LayoutMediaControls::formatMediaControlsTime(float time) | |
| 474 { | |
| 475 return formatChromiumMediaControlsTime(time, time); | |
| 476 } | |
| 477 | |
| 478 String LayoutMediaControls::formatMediaControlsCurrentTime(float currentTime, fl
oat duration) | |
| 479 { | |
| 480 return formatChromiumMediaControlsTime(currentTime, duration); | |
| 481 } | |
| 482 | |
| 483 } // namespace blink | |
| OLD | NEW |