1 /*
   2  * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "config.h"
  27 
  28 #include <cstdio>
  29 #include <wtf/Vector.h>
  30 #include <wtf/text/StringBuilder.h>
  31 
  32 #include "Chrome.h"
  33 #include "ChromeClientJava.h"
  34 #include "CSSPropertyNames.h"
  35 #include "CSSFontSelector.h"
  36 #include "CSSValueKeywords.h"
  37 #include <wtf/java/JavaEnv.h>
  38 #include "HTMLMediaElement.h"
  39 #include "NotImplemented.h"
  40 #include "PaintInfo.h"
  41 #include "PlatformContextJava.h"
  42 #include "RenderObject.h"
  43 #if ENABLE(PROGRESS_ELEMENT)
  44 #include "RenderProgress.h"
  45 #endif
  46 #if ENABLE(METER_ELEMENT)
  47 #include "HTMLMeterElement.h"
  48 #endif
  49 #include "RenderSlider.h"
  50 #include "RenderThemeJava.h"
  51 #include "ThemeTypes.h"
  52 #include "TimeRanges.h"
  53 #include "UserAgentScripts.h"
  54 #include "UserAgentStyleSheets.h"
  55 #include "MediaControlElementTypes.h"
  56 #include "Page.h"
  57 
  58 #include "com_sun_webkit_graphics_RenderTheme.h"
  59 #include "com_sun_webkit_graphics_GraphicsDecoder.h"
  60 #include "com_sun_webkit_graphics_RenderMediaControls.h"
  61 
  62 
  63 #define RENDER_MEDIA_CONTROLS_CLASS_NAME    "com/sun/webkit/graphics/RenderMediaControls"
  64 
  65 #define JNI_EXPAND(n) com_sun_webkit_graphics_RenderTheme_##n
  66 #define JNI_EXPAND_MEDIA(n) com_sun_webkit_graphics_RenderMediaControls_##n
  67 
  68 namespace WebCore {
  69 
  70 RenderTheme& RenderTheme::singleton()
  71 {
  72     static RenderTheme& sm_defaultInstance = *new RenderThemeJava();
  73     return sm_defaultInstance;
  74 }
  75 
  76 jclass getJRenderThemeClass()
  77 {
  78     static JGClass jRenderThemeCls(
  79         WebCore_GetJavaEnv()->FindClass("com/sun/webkit/graphics/RenderTheme"));
  80     ASSERT(jRenderThemeCls);
  81 
  82     return jRenderThemeCls;
  83 }
  84 
  85 static JLObject getJRenderTheme(JLObject page)
  86 {
  87     JNIEnv* env = WebCore_GetJavaEnv();
  88 
  89     if (!page) {
  90         static jmethodID mid  = env->GetStaticMethodID(
  91             PG_GetWebPageClass(env),
  92             "fwkGetDefaultRenderTheme",
  93             "()Lcom/sun/webkit/graphics/RenderTheme;");
  94         ASSERT(mid);
  95 
  96         JLObject jRenderTheme(env->CallStaticObjectMethod(PG_GetWebPageClass(env), mid));
  97         CheckAndClearException(env);
  98 
  99         return jRenderTheme;
 100     }
 101 
 102     static jmethodID mid  = env->GetMethodID(
 103         PG_GetWebPageClass(env),
 104         "getRenderTheme",
 105         "()Lcom/sun/webkit/graphics/RenderTheme;");
 106     ASSERT(mid);
 107 
 108     JLObject jRenderTheme(env->CallObjectMethod(
 109         page,
 110         mid));
 111     CheckAndClearException(env);
 112 
 113     return jRenderTheme;
 114 }
 115 
 116 RefPtr<RQRef> RenderThemeJava::themeForPage(JLObject page)
 117 {
 118     return RQRef::create(getJRenderTheme(page));
 119 }
 120 
 121 RenderThemeJava::RenderThemeJava()
 122 {
 123 }
 124 
 125 int RenderThemeJava::createWidgetState(const RenderObject& o)
 126 {
 127     int state = 0;
 128     if (isChecked(o))
 129         state |= JNI_EXPAND(CHECKED);
 130     if (isIndeterminate(o))
 131         state |= JNI_EXPAND(INDETERMINATE);
 132     if (isEnabled(o))
 133         state |= JNI_EXPAND(ENABLED);
 134     if (isFocused(o))
 135         state |= JNI_EXPAND(FOCUSED);
 136     if (isPressed(o))
 137         state |= JNI_EXPAND(PRESSED);
 138     if (isHovered(o))
 139         state |= JNI_EXPAND(HOVERED);
 140     if (isReadOnlyControl(o))
 141         state |= JNI_EXPAND(READ_ONLY);
 142     return state;
 143 }
 144 
 145 bool RenderThemeJava::paintWidget(
 146     int widgetIndex,
 147     const RenderObject& object,
 148     const PaintInfo &paintInfo,
 149     const FloatRect &rect) {
 150 
 151     return paintWidget(widgetIndex, object, paintInfo, enclosingIntRect(rect));
 152 }
 153 
 154 bool RenderThemeJava::paintWidget(
 155     int widgetIndex,
 156     const RenderObject& object,
 157     const PaintInfo &paintInfo,
 158     const IntRect &rect)
 159 {
 160     // platformContext() returns 0 when printing
 161     if (paintInfo.context().paintingDisabled() || !paintInfo.context().platformContext()) {
 162         return false;
 163     }
 164 
 165     auto jRenderTheme = paintInfo.context().platformContext()->jRenderTheme();
 166     if (!jRenderTheme) {
 167         return false;
 168     }
 169 
 170     int state = createWidgetState(object);
 171     RGBA32 bgColor = object.style().visitedDependentColor(
 172         widgetIndex == JNI_EXPAND(MENU_LIST_BUTTON)
 173             ? CSSPropertyColor
 174             : CSSPropertyBackgroundColor
 175     ).rgb();
 176 
 177     JNIEnv* env = WebCore_GetJavaEnv();
 178 
 179     WTF::Vector<jbyte> extParams;
 180     if (JNI_EXPAND(SLIDER) == widgetIndex) {
 181         HTMLInputElement& input = downcast<RenderSlider>(object).element();
 182 
 183         extParams.grow(sizeof(jint) + 3 * sizeof(jfloat));
 184         jbyte *data = extParams.data();
 185         auto isVertical = jint((object.style().appearance() == SliderHorizontalPart)
 186             ? 0
 187             : 1);
 188         memcpy(data, &isVertical, sizeof(isVertical));
 189         data += sizeof(jint);
 190 
 191         auto maximum = jfloat(input.maximum());
 192         memcpy(data, &maximum, sizeof(maximum));
 193         data += sizeof(jfloat);
 194 
 195         auto minimum = jfloat(input.minimum());
 196         memcpy(data, &minimum, sizeof(minimum));
 197         data += sizeof(jfloat);
 198 
 199         auto valueAsNumber = jfloat(input.valueAsNumber());
 200         memcpy(data, &valueAsNumber, sizeof(valueAsNumber));
 201     } else if (JNI_EXPAND(PROGRESS_BAR) == widgetIndex) {
 202 #if ENABLE(PROGRESS_ELEMENT)
 203         RenderProgress& renderProgress = downcast<RenderProgress>(object);
 204 
 205         extParams.grow(sizeof(jint) + 3*sizeof(jfloat));
 206         jbyte *data = extParams.data();
 207         auto isDeterminate = jint(renderProgress.isDeterminate() ? 1 : 0);
 208         memcpy(data, &isDeterminate, sizeof(isDeterminate));
 209         data += sizeof(jint);
 210 
 211         auto position = jfloat(renderProgress.position());
 212         memcpy(data, &position, sizeof(position));
 213         data += sizeof(jfloat);
 214 
 215         auto animationProgress = jfloat(renderProgress.animationProgress());
 216         memcpy(data, &animationProgress, sizeof(animationProgress));
 217         data += sizeof(jfloat);
 218 
 219         auto animationStartTime = jfloat(renderProgress.animationStartTime());
 220         memcpy(data, &animationStartTime, sizeof(animationStartTime));
 221 #endif
 222 #if ENABLE(METER_ELEMENT)
 223     } else if (JNI_EXPAND(METER) == widgetIndex) {
 224         jfloat value = 0;
 225         jint region = 0;
 226         if (object.isMeter()) {
 227             HTMLMeterElement* meter = static_cast<HTMLMeterElement*>(object.node());
 228             value = meter->valueRatio();
 229             region = meter->gaugeRegion();
 230 #if ENABLE(PROGRESS_ELEMENT)
 231         } else if (object.isProgress()) {
 232             RenderProgress& renderProgress = downcast<RenderProgress>(object);
 233             value = jfloat(renderProgress.position());
 234 #endif
 235         }
 236 
 237         extParams.grow(sizeof(jfloat) + sizeof(jint));
 238         jbyte *data = extParams.data();
 239         memcpy(data, &value, sizeof(value));
 240         data += sizeof(jfloat);
 241 
 242         memcpy(data, &region, sizeof(region));
 243 #endif
 244     }
 245 
 246     static jmethodID mid = env->GetMethodID(getJRenderThemeClass(), "createWidget",
 247             "(JIIIIILjava/nio/ByteBuffer;)Lcom/sun/webkit/graphics/Ref;");
 248     ASSERT(mid);
 249 
 250     RefPtr<RQRef> widgetRef = RQRef::create(
 251         env->CallObjectMethod(jobject(*jRenderTheme), mid,
 252             ptr_to_jlong(&object),
 253             (jint)widgetIndex,
 254             (jint)state,
 255             (jint)rect.width(), (jint)rect.height(),
 256             (jint)bgColor,
 257             (jobject)JLObject(extParams.isEmpty()
 258                 ? nullptr
 259                 : env->NewDirectByteBuffer(
 260                     extParams.data(),
 261                     extParams.size())))
 262         );
 263     if (!widgetRef.get()) {
 264         //switch to WebKit default render
 265         return true;
 266     }
 267     CheckAndClearException(env);
 268 
 269     // widgetRef will go into rq's inner refs vector.
 270     paintInfo.context().platformContext()->rq().freeSpace(20)
 271     << (jint)com_sun_webkit_graphics_GraphicsDecoder_DRAWWIDGET
 272     << (jint)*jRenderTheme
 273     << widgetRef
 274     << (jint)rect.x() << (jint)rect.y();
 275 
 276     return false;
 277 }
 278 
 279 #if ENABLE(PROGRESS_ELEMENT)
 280 void RenderThemeJava::adjustProgressBarStyle(StyleResolver&, RenderStyle& style, const Element*) const
 281 {
 282     style.setBoxShadow(nullptr);
 283 }
 284 
 285 //utatodo: ask Java theme
 286 // These values have been copied from RenderThemeChromiumSkia.cpp
 287 static const int progressActivityBlocks = 5;
 288 static const int progressAnimationFrames = 10;
 289 static const double progressAnimationInterval = 0.125;
 290 double RenderThemeJava::animationRepeatIntervalForProgressBar(RenderProgress&) const
 291 {
 292     return progressAnimationInterval;
 293 }
 294 
 295 double RenderThemeJava::animationDurationForProgressBar(RenderProgress&) const
 296 {
 297     return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth;
 298 }
 299 
 300 bool RenderThemeJava::paintProgressBar(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 301 {
 302     return paintWidget(JNI_EXPAND(PROGRESS_BAR), o, i, rect);
 303 }
 304 #endif
 305 
 306 #if ENABLE(METER_ELEMENT)
 307 bool RenderThemeJava::supportsMeter(ControlPart part) const
 308 {
 309 #if ENABLE(PROGRESS_ELEMENT)
 310     if (part == ProgressBarPart) {
 311         return true;
 312     }
 313 #endif
 314     return (part == MeterPart);
 315 }
 316 
 317 bool RenderThemeJava::paintMeter(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 318 {
 319     return paintWidget(JNI_EXPAND(METER), o, i, rect);
 320 }
 321 #endif
 322 
 323 void RenderThemeJava::setCheckboxSize(RenderStyle& style) const
 324 {
 325     setRadioSize(style);
 326 }
 327 
 328 bool RenderThemeJava::paintCheckbox(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 329 {
 330     return paintWidget(JNI_EXPAND(CHECK_BOX), o, i, rect);
 331 }
 332 
 333 void RenderThemeJava::setRadioSize(RenderStyle& style) const
 334 {
 335     // If the width and height are both specified, then we have nothing to do.
 336     if ((!style.width().isIntrinsicOrAuto() && !style.height().isAuto())) {
 337         return;
 338     }
 339 
 340     JNIEnv* env = WebCore_GetJavaEnv();
 341 
 342     static jmethodID mid = env->GetMethodID(getJRenderThemeClass(), "getRadioButtonSize", "()I");
 343     ASSERT(mid);
 344 
 345     // Get from default theme object.
 346     int radioRadius = env->CallIntMethod((jobject)getJRenderTheme(nullptr), mid);
 347     CheckAndClearException(env);
 348 
 349     if (style.width().isIntrinsicOrAuto()) {
 350         style.setWidth(Length(radioRadius, Fixed));
 351     }
 352 
 353     if (style.height().isAuto()) {
 354         style.setHeight(Length(radioRadius, Fixed));
 355     }
 356 }
 357 
 358 bool RenderThemeJava::paintRadio(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 359 {
 360     return paintWidget(JNI_EXPAND(RADIO_BUTTON), o, i, rect);
 361 }
 362 
 363 bool RenderThemeJava::paintButton(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 364 {
 365     return paintWidget(JNI_EXPAND(BUTTON), o, i, rect);
 366 }
 367 
 368 void RenderThemeJava::adjustTextFieldStyle(StyleResolver&, RenderStyle&, const Element*) const
 369 {
 370     notImplemented();
 371 }
 372 
 373 bool RenderThemeJava::paintTextField(const RenderObject&o, const PaintInfo& i, const FloatRect& rect)
 374 {
 375     return paintWidget(JNI_EXPAND(TEXT_FIELD), o, i, rect);
 376 }
 377 
 378 void RenderThemeJava::adjustSearchFieldStyle(StyleResolver&, RenderStyle&, const Element*) const
 379 {
 380     notImplemented();
 381 }
 382 
 383 bool RenderThemeJava::paintSearchField(const RenderObject&o, const PaintInfo& i, const IntRect& rect)
 384 {
 385     return paintWidget(JNI_EXPAND(TEXT_FIELD), o, i, rect);
 386 }
 387 
 388 void RenderThemeJava::adjustTextAreaStyle(StyleResolver&, RenderStyle& style, const Element*) const
 389 {
 390     if (style.paddingTop().isIntrinsicOrAuto())
 391         style.setPaddingTop(Length(1, Fixed));
 392     if (style.paddingBottom().isIntrinsicOrAuto())
 393         style.setPaddingBottom(Length(1, Fixed));
 394 }
 395 
 396 bool RenderThemeJava::paintTextArea(const RenderObject&o, const PaintInfo& i, const FloatRect& r)
 397 {
 398     return paintTextField(o, i, r);
 399 }
 400 
 401 void RenderThemeJava::adjustButtonStyle(StyleResolver&, RenderStyle& style, const Element*) const
 402 {
 403     if (style.appearance() == PushButtonPart) {
 404         // Ignore line-height.
 405         style.setLineHeight(RenderStyle::initialLineHeight());
 406     }
 407 }
 408 
 409 enum JavaControlSize {
 410     JavaRegularControlSize, // The control is sized as regular.
 411     JavaSmallControlSize,   // The control has a smaller size.
 412     JavaMiniControlSize     // The control has a smaller size than JavaSmallControlSize.
 413 };
 414 
 415 static float systemFontSizeForControlSize(JavaControlSize controlSize)
 416 {
 417     static float sizes[] = { 16.0f, 13.0f, 10.0f };
 418 
 419     return sizes[controlSize];
 420 }
 421 
 422 void RenderThemeJava::updateCachedSystemFontDescription(CSSValueID propId, FontCascadeDescription& fontDescription) const
 423 {
 424     // This logic owes much to RenderThemeSafari.cpp.
 425     static FontCascadeDescription systemFont;
 426     static FontCascadeDescription smallSystemFont;
 427     static FontCascadeDescription menuFont;
 428     static FontCascadeDescription labelFont;
 429     static FontCascadeDescription miniControlFont;
 430     static FontCascadeDescription smallControlFont;
 431     static FontCascadeDescription controlFont;
 432 
 433     FontCascadeDescription* cachedDesc;
 434     float fontSize = 0;
 435     switch (propId) {
 436         case CSSValueSmallCaption:
 437             cachedDesc = &smallSystemFont;
 438             if (!smallSystemFont.isAbsoluteSize())
 439                 fontSize = systemFontSizeForControlSize(JavaSmallControlSize);
 440             break;
 441         case CSSValueMenu:
 442             cachedDesc = &menuFont;
 443             if (!menuFont.isAbsoluteSize())
 444                 fontSize = systemFontSizeForControlSize(JavaRegularControlSize);
 445             break;
 446         case CSSValueStatusBar:
 447             cachedDesc = &labelFont;
 448             if (!labelFont.isAbsoluteSize())
 449                 fontSize = 10.0f;
 450             break;
 451         case CSSValueWebkitMiniControl:
 452             cachedDesc = &miniControlFont;
 453             if (!miniControlFont.isAbsoluteSize())
 454                 fontSize = systemFontSizeForControlSize(JavaMiniControlSize);
 455             break;
 456         case CSSValueWebkitSmallControl:
 457             cachedDesc = &smallControlFont;
 458             if (!smallControlFont.isAbsoluteSize())
 459                 fontSize = systemFontSizeForControlSize(JavaSmallControlSize);
 460             break;
 461         case CSSValueWebkitControl:
 462             cachedDesc = &controlFont;
 463             if (!controlFont.isAbsoluteSize())
 464                 fontSize = systemFontSizeForControlSize(JavaRegularControlSize);
 465             break;
 466         default:
 467             cachedDesc = &systemFont;
 468             if (!systemFont.isAbsoluteSize())
 469                 fontSize = 13.0f;
 470     }
 471 
 472     if (fontSize) {
 473         cachedDesc->setIsAbsoluteSize(true);
 474         // cachedDesc->setGenericFamily(FontCascadeDescription::NoFamily);
 475         //cachedDesc->setOneFamily("Lucida Grande");
 476         cachedDesc->setOneFamily("Tahoma");
 477         cachedDesc->setSpecifiedSize(fontSize);
 478         cachedDesc->setWeight(normalWeightValue());
 479         cachedDesc->setItalic(normalItalicValue());
 480     }
 481     fontDescription = *cachedDesc;
 482 }
 483 
 484 void RenderThemeJava::adjustSliderTrackStyle(StyleResolver& selector, RenderStyle& style, const Element* element) const
 485 {
 486     //utatodo: we need to measure the control in Java theme.
 487     RenderTheme::adjustSliderTrackStyle(selector, style, element);
 488 }
 489 
 490 bool RenderThemeJava::paintSliderTrack(const RenderObject&object, const PaintInfo& info, const IntRect& rect)
 491 {
 492     return paintWidget(JNI_EXPAND(SLIDER), object, info, rect);
 493 }
 494 
 495 void getSliderThumbSize(jint sliderType, int *width, int *height)
 496 {
 497     JNIEnv* env = WebCore_GetJavaEnv();
 498     JGClass cls = JLClass(env->FindClass(RENDER_MEDIA_CONTROLS_CLASS_NAME));
 499     ASSERT(cls);
 500 
 501     jmethodID mid = env->GetStaticMethodID(cls, "fwkGetSliderThumbSize", "(I)I");
 502     ASSERT(mid);
 503 
 504     jint size = env->CallStaticIntMethod(cls, mid, sliderType);
 505     CheckAndClearException(env);
 506     *width = (size >> 16) & 0xFFFF;
 507     *height = size & 0xFFFF;
 508 }
 509 
 510 //utatodo: we need to measure the control in Java theme, do not make it const
 511 const int sliderThumbWidth = 17;
 512 const int sliderThumbHeight = 17;
 513 
 514 void RenderThemeJava::adjustSliderThumbSize(RenderStyle& style, const Element*) const
 515 {
 516     ControlPart part = style.appearance();
 517 #if ENABLE(VIDEO)
 518     if (part == SliderThumbVerticalPart || part == SliderThumbHorizontalPart)
 519 #endif
 520     {
 521         style.setWidth(Length(sliderThumbHeight, Fixed));
 522         style.setHeight(Length(sliderThumbWidth, Fixed));
 523     }
 524 #if ENABLE(VIDEO)
 525     else if (part == MediaSliderThumbPart) {
 526         static int timeWidth = 0;
 527         static int timeHeight;
 528         if (timeWidth == 0) {
 529             getSliderThumbSize(JNI_EXPAND_MEDIA(SLIDER_TYPE_TIME), &timeWidth, &timeHeight);
 530         }
 531         style.setWidth(Length(timeWidth, Fixed));
 532         style.setHeight(Length(timeHeight, Fixed));
 533     } else if (part == MediaVolumeSliderThumbPart) {
 534         static int volumeWidth = 0;
 535         static int volumeHeight;
 536         if (volumeWidth == 0) {
 537             getSliderThumbSize(JNI_EXPAND_MEDIA(SLIDER_TYPE_VOLUME), &volumeWidth, &volumeHeight);
 538         }
 539         style.setWidth(Length(volumeWidth, Fixed));
 540         style.setHeight(Length(volumeHeight, Fixed));
 541     }
 542 #endif
 543 }
 544 
 545 bool RenderThemeJava::paintSliderThumb(const RenderObject&, const PaintInfo&, const IntRect&)
 546 {
 547     // We've already painted it in paintSliderTrack(), no need to do anything here.
 548     return false;
 549 }
 550 
 551 void RenderThemeJava::adjustMenuListStyle(StyleResolver&, RenderStyle& style, const Element*) const
 552 {
 553     // Add in the padding that we'd like to use.
 554     style.setPaddingRight(Length(20.0f + style.paddingRight().value(), Fixed));
 555     style.setPaddingLeft(Length(2.0f + style.paddingLeft().value(), Fixed));
 556 }
 557 
 558 bool RenderThemeJava::paintMenuList(const RenderObject& o, const PaintInfo& i, const FloatRect& rect)
 559 {
 560     return paintWidget(JNI_EXPAND(MENU_LIST), o, i, rect);
 561 }
 562 
 563 void RenderThemeJava::adjustMenuListButtonStyle(StyleResolver& selector, RenderStyle& style, const Element* e) const
 564 {
 565     style.resetBorderRadius();
 566     adjustMenuListStyle(selector, style, e);
 567 }
 568 
 569 bool RenderThemeJava::paintMenuListButtonDecorations(const RenderBox& o, const PaintInfo& i, const FloatRect& r)
 570 {
 571     IntRect rect(r.x() + r.width(), r.y(), r.height(), r.height());
 572 
 573     return paintWidget(JNI_EXPAND(MENU_LIST_BUTTON), o, i, rect);
 574 }
 575 
 576 bool RenderThemeJava::supportsFocusRing(const RenderStyle& style) const
 577 {
 578     if (!style.hasAppearance())
 579         return false;
 580 
 581     switch (style.appearance()) {
 582     case TextFieldPart:
 583     case TextAreaPart:
 584     case ButtonPart:
 585     case CheckboxPart:
 586     case RadioPart:
 587     case MenulistPart:
 588         return true;
 589     default:
 590         return RenderTheme::supportsFocusRing(style);
 591     }
 592 }
 593 
 594 Color RenderThemeJava::getSelectionColor(int index) const
 595 {
 596     JNIEnv* env = WebCore_GetJavaEnv();
 597     ASSERT(env);
 598 
 599     static jmethodID mid = env->GetMethodID(getJRenderThemeClass(), "getSelectionColor", "(I)I");
 600     ASSERT(mid);
 601 
 602     // Get from default theme object.
 603     jint c = env->CallIntMethod((jobject)getJRenderTheme(nullptr), mid, index);
 604     CheckAndClearException(env);
 605 
 606     return Color(c);
 607 }
 608 
 609 Color RenderThemeJava::platformActiveSelectionBackgroundColor() const
 610 {
 611     return getSelectionColor(JNI_EXPAND(BACKGROUND));
 612 }
 613 
 614 Color RenderThemeJava::platformInactiveSelectionBackgroundColor() const
 615 {
 616     return platformActiveSelectionBackgroundColor();
 617 }
 618 
 619 Color RenderThemeJava::platformActiveSelectionForegroundColor() const
 620 {
 621     return getSelectionColor(JNI_EXPAND(FOREGROUND));
 622 }
 623 
 624 Color RenderThemeJava::platformInactiveSelectionForegroundColor() const
 625 {
 626     return platformActiveSelectionForegroundColor();
 627 }
 628 
 629 #if ENABLE(VIDEO)
 630 String RenderThemeJava::mediaControlsScript()
 631 {
 632     StringBuilder scriptBuilder;
 633     scriptBuilder.append(mediaControlsLocalizedStringsJavaScript, sizeof(mediaControlsLocalizedStringsJavaScript));
 634     scriptBuilder.append(mediaControlsBaseJavaScript, sizeof(mediaControlsBaseJavaScript));
 635     scriptBuilder.append(mediaControlsGtkJavaScript, sizeof(mediaControlsGtkJavaScript));
 636     return scriptBuilder.toString();
 637 }
 638 
 639 String RenderThemeJava::extraMediaControlsStyleSheet()
 640 {
 641     return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet));
 642 }
 643 
 644 String RenderThemeJava::formatMediaControlsCurrentTime(float, float) const
 645 {
 646     return "";
 647 }
 648 
 649 String RenderThemeJava::formatMediaControlsRemainingTime(float currentTime, float duration) const
 650 {
 651     return formatMediaControlsTime(currentTime) + "/" + formatMediaControlsTime(duration);
 652 }
 653 
 654 /*
 655 bool RenderThemeJava::paintMediaFullscreenButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 656 */
 657 
 658 bool RenderThemeJava::paintMediaPlayButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
 659 {
 660     auto mediaElement = parentMediaElement(o);
 661     if (mediaElement == nullptr)
 662         return false;
 663 
 664     // readyState can be NETWORK_EMPTY if preload is NONE
 665     jint type = mediaElement->readyState() == HTMLMediaElementEnums::ReadyState::HAVE_NOTHING
 666                     ? JNI_EXPAND_MEDIA(DISABLED_PLAY_BUTTON)
 667                     : mediaElement->paused()
 668                         ? JNI_EXPAND_MEDIA(PLAY_BUTTON)
 669                         : JNI_EXPAND_MEDIA(PAUSE_BUTTON);
 670     return paintMediaControl(type, o, paintInfo, r);
 671 }
 672 
 673 bool RenderThemeJava::paintMediaMuteButton(const RenderObject&o, const PaintInfo& paintInfo, const IntRect& r)
 674 {
 675     auto mediaElement = parentMediaElement(o);
 676     if (mediaElement == nullptr)
 677         return false;
 678 
 679     jint type = !mediaElement->hasAudio()
 680                     ? JNI_EXPAND_MEDIA(DISABLED_MUTE_BUTTON)
 681                     : mediaElement->muted()
 682                         ? JNI_EXPAND_MEDIA(UNMUTE_BUTTON)
 683                         : JNI_EXPAND_MEDIA(MUTE_BUTTON);
 684     return paintMediaControl(type, o, paintInfo, r);
 685 }
 686 
 687 /*
 688 bool RenderThemeJava::paintMediaSeekBackButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 689 bool RenderThemeJava::paintMediaSeekForwardButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 690 */
 691 
 692 bool RenderThemeJava::paintMediaSliderTrack(const RenderObject&o, const PaintInfo& paintInfo, const IntRect& r)
 693 {
 694     auto mediaElement = parentMediaElement(o);
 695     if (mediaElement == nullptr)
 696         return false;
 697 
 698     Ref<TimeRanges> timeRanges = mediaElement->buffered();
 699 
 700     paintInfo.context().platformContext()->rq().freeSpace(4
 701         + 4                 // number of timeRange pairs
 702         + timeRanges->length() * 4 *2   // timeRange pairs
 703         + 4 + 4             // duration and currentTime
 704         + 4 + 4 + 4 + 4     // x, y, w, h
 705         )
 706     << (jint)com_sun_webkit_graphics_GraphicsDecoder_RENDERMEDIA_TIMETRACK
 707     << (jint)timeRanges->length();
 708 
 709     //utatodo: need [double] support
 710     for (unsigned i = 0; i < timeRanges->length(); i++) {
 711         paintInfo.context().platformContext()->rq()
 712         << (jfloat)timeRanges->start(i).releaseReturnValue() << (jfloat)timeRanges->end(i).releaseReturnValue();
 713     }
 714 
 715     paintInfo.context().platformContext()->rq()
 716     << (jfloat)mediaElement->duration()
 717     << (jfloat)mediaElement->currentTime()
 718     << (jint)r.x() <<  (jint)r.y() << (jint)r.width() << (jint)r.height();
 719     return true;
 720 }
 721 
 722 bool RenderThemeJava::paintMediaSliderThumb(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
 723 {
 724     return paintMediaControl(JNI_EXPAND_MEDIA(TIME_SLIDER_THUMB), o, paintInfo, r);
 725 }
 726 
 727 bool RenderThemeJava::paintMediaVolumeSliderContainer(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
 728 {
 729     return paintMediaControl(JNI_EXPAND_MEDIA(VOLUME_CONTAINER), o, paintInfo, r);
 730 }
 731 
 732 bool RenderThemeJava::paintMediaVolumeSliderTrack(const RenderObject& o, const PaintInfo& paintInfo, const IntRect& r)
 733 {
 734     auto mediaElement = parentMediaElement(o);
 735     if (mediaElement == nullptr)
 736         return false;
 737 
 738     paintInfo.context().platformContext()->rq().freeSpace(28)
 739     << (jint)com_sun_webkit_graphics_GraphicsDecoder_RENDERMEDIA_VOLUMETRACK
 740     << (jfloat)mediaElement->volume()
 741     << (jint)(mediaElement->hasAudio() && !mediaElement->muted() ? 0 : 1)   // muted
 742     << (jint)r.x() <<  (jint)r.y() << (jint)r.width() << (jint)r.height();
 743     return true;
 744 
 745 }
 746 
 747 bool RenderThemeJava::paintMediaVolumeSliderThumb(const RenderObject& object, const PaintInfo& paintInfo, const IntRect& rect)
 748 {
 749     return paintMediaControl(JNI_EXPAND_MEDIA(VOLUME_THUMB), object, paintInfo, rect);
 750 }
 751 
 752 /*
 753 bool RenderThemeJava::paintMediaRewindButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 754 bool RenderThemeJava::paintMediaReturnToRealtimeButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 755 bool RenderThemeJava::paintMediaToggleClosedCaptionsButton(const RenderObject& o, const PaintInfo& paintInfo, const IntRect &r);
 756 */
 757 
 758 bool RenderThemeJava::paintMediaControlsBackground(const RenderObject&, const PaintInfo&, const IntRect&)
 759 {
 760 //    return paintMediaControl(JNI_EXPAND_MEDIA(BACKGROUND), o, paintInfo, r);
 761     return true;
 762 }
 763 
 764 bool RenderThemeJava::paintMediaCurrentTime(const RenderObject&, const PaintInfo&, const IntRect&)
 765 {
 766 //    return paintMediaControl(JNI_EXPAND_MEDIA(CURRENT_TIME), o, paintInfo, r);
 767     return true;
 768 }
 769 
 770 bool RenderThemeJava::paintMediaTimeRemaining(const RenderObject&, const PaintInfo&, const IntRect&)
 771 {
 772 //    return paintMediaControl(JNI_EXPAND_MEDIA(REMAINING_TIME), o, paintInfo, r);
 773     return true;
 774 }
 775 
 776 bool RenderThemeJava::paintMediaControl(jint type, const RenderObject&, const PaintInfo& paintInfo, const IntRect& r)
 777 {
 778     paintInfo.context().platformContext()->rq().freeSpace(24)
 779     << (jint)com_sun_webkit_graphics_GraphicsDecoder_RENDERMEDIACONTROL
 780     << type << (jint)r.x() <<  (jint)r.y()
 781     << (jint)r.width() << (jint)r.height();
 782 
 783     return true;
 784 }
 785 
 786 
 787 #undef JNI_EXPAND_MEDIA
 788 
 789 #endif  // ENABLE(VIDEO)
 790 
 791 }
 792 
 793 #undef JNI_EXPAND
 794