25fc5137991f8b7424adaaeae6b325b5ef07293f
[WebKit-https.git] / Source / WebCore / platform / efl / RenderThemeEfl.cpp
1 /*
2  * Copyright (C) 2007 Apple Inc.
3  * Copyright (C) 2007 Alp Toker <alp@atoker.com>
4  * Copyright (C) 2008 Collabora Ltd.
5  * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
6  * Copyright (C) 2009-2010 ProFUSION embedded systems
7  * Copyright (C) 2009-2011 Samsung Electronics
8  * Copyright (c) 2012 Intel Corporation. All rights reserved.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  *
25  */
26
27 #include "config.h"
28 #include "RenderThemeEfl.h"
29
30 #include "CSSValueKeywords.h"
31 #include "CairoUtilitiesEfl.h"
32 #include "ExceptionCodePlaceholder.h"
33 #include "FontDescription.h"
34 #include "GraphicsContext.h"
35 #include "HTMLInputElement.h"
36 #include "InputTypeNames.h"
37 #include "NotImplemented.h"
38 #include "Page.h"
39 #include "PaintInfo.h"
40 #include "PlatformContextCairo.h"
41 #include "RenderBox.h"
42 #include "RenderObject.h"
43 #include "RenderProgress.h"
44 #include "RenderSlider.h"
45 #include "UserAgentStyleSheets.h"
46
47 #include <Ecore_Evas.h>
48 #include <Edje.h>
49 #include <new>
50 #include <wtf/text/CString.h>
51 #include <wtf/text/WTFString.h>
52
53 #if ENABLE(VIDEO)
54 #include "HTMLMediaElement.h"
55 #include "HTMLNames.h"
56 #include "TimeRanges.h"
57 #endif
58
59 namespace WebCore {
60 #if ENABLE(VIDEO)
61 using namespace HTMLNames;
62 #endif
63
64 // TODO: change from object count to ecore_evas size (bytes)
65 // TODO: as objects are webpage/user defined and they can be very large.
66 #define RENDER_THEME_EFL_PART_CACHE_MAX 32
67
68 // Initialize default font size.
69 float RenderThemeEfl::defaultFontSize = 16.0f;
70
71 // Constants for progress tag animation.
72 // These values have been copied from RenderThemeGtk.cpp
73 static const int progressAnimationFrames = 10;
74 static const double progressAnimationInterval = 0.125;
75
76 static const int sliderThumbWidth = 29;
77 static const int sliderThumbHeight = 11;
78 #if ENABLE(VIDEO)
79 static const int mediaSliderHeight = 14;
80 static const int mediaSliderThumbWidth = 12;
81 static const int mediaSliderThumbHeight = 12;
82 #endif
83
84 #define _ASSERT_ON_RELEASE_RETURN(o, fmt, ...) \
85     do { if (!o) { EINA_LOG_CRIT(fmt, ## __VA_ARGS__); ASSERT(o); return; } } while (0)
86 #define _ASSERT_ON_RELEASE_RETURN_VAL(o, val, fmt, ...) \
87     do { if (!o) { EINA_LOG_CRIT(fmt, ## __VA_ARGS__); ASSERT(o); return val; } } while (0)
88
89
90 static const char* toEdjeGroup(FormType type)
91 {
92     static const char* groups[] = {
93 #define W(n) "webkit/widget/"n
94         W("button"),
95         W("radio"),
96         W("entry"),
97         W("checkbox"),
98         W("combo"),
99 #if ENABLE(PROGRESS_ELEMENT)
100         W("progressbar"),
101 #endif
102         W("search/field"),
103         W("search/decoration"),
104         W("search/results_button"),
105         W("search/results_decoration"),
106         W("search/cancel_button"),
107         W("slider/vertical"),
108         W("slider/horizontal"),
109         W("slider/thumb_vertical"),
110         W("slider/thumb_horizontal"),
111 #if ENABLE(VIDEO)
112         W("mediacontrol/playpause_button"),
113         W("mediacontrol/mute_button"),
114         W("mediacontrol/seekforward_button"),
115         W("mediacontrol/seekbackward_button"),
116         W("mediacontrol/fullscreen_button"),
117 #endif
118 #if ENABLE(VIDEO_TRACK)
119         W("mediacontrol/toggle_captions_button"),
120 #endif
121         W("spinner"),
122 #undef W
123         0
124     };
125     ASSERT(type >= 0);
126     ASSERT((size_t)type < sizeof(groups) / sizeof(groups[0])); // Out of sync?
127     return groups[type];
128 }
129
130 static bool setSourceGroupForEdjeObject(Evas_Object* o, const String& themePath, const char* group)
131 {
132     ASSERT(o);
133     ASSERT(!themePath.isEmpty());
134
135     if (!edje_object_file_set(o, themePath.utf8().data(), group)) {
136         const char* message = edje_load_error_str(edje_object_load_error_get(o));
137         EINA_LOG_ERR("Could not set theme group '%s' of file '%s': %s", group, themePath.utf8().data(), message);
138         return false;
139     }
140
141     return true;
142 }
143
144 void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) const
145 {
146     loadThemeIfNeeded();
147
148     // These are always valid, even if no theme could be loaded.
149     const ThemePartDesc* desc = m_partDescs + (size_t)type;
150
151     if (style->minWidth().isIntrinsic())
152         style->setMinWidth(desc->min.width());
153     if (style->minHeight().isIntrinsic())
154         style->setMinHeight(desc->min.height());
155
156     if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto())
157         style->setMaxWidth(desc->max.width());
158     if (desc->max.height().value() > 0 && style->maxHeight().isIntrinsicOrAuto())
159         style->setMaxHeight(desc->max.height());
160
161     style->setPaddingTop(desc->padding.top());
162     style->setPaddingBottom(desc->padding.bottom());
163     style->setPaddingLeft(desc->padding.left());
164     style->setPaddingRight(desc->padding.right());
165 }
166
167 static bool isFormElementTooLargeToDisplay(const IntSize& elementSize)
168 {
169     // This limit of 20000 pixels is hardcoded inside edje -- anything above this size
170     // will be clipped. This value seems to be reasonable enough so that hardcoding it
171     // here won't be a problem.
172     static const int maxEdjeDimension = 20000;
173
174     return elementSize.width() > maxEdjeDimension || elementSize.height() > maxEdjeDimension;
175 }
176
177 PassOwnPtr<RenderThemeEfl::ThemePartCacheEntry> RenderThemeEfl::ThemePartCacheEntry::create(const String& themePath, FormType type, const IntSize& size)
178 {
179     ASSERT(!themePath.isEmpty());
180
181     if (isFormElementTooLargeToDisplay(size) || size.isEmpty()) {
182         EINA_LOG_ERR("Cannot render an element of size %dx%d.", size.width(), size.height());
183         return nullptr;
184     }
185
186     OwnPtr<ThemePartCacheEntry> entry = adoptPtr(new ThemePartCacheEntry);
187
188     entry->m_canvas = adoptPtr(ecore_evas_buffer_new(size.width(), size.height()));
189     if (!entry->canvas()) {
190         EINA_LOG_ERR("ecore_evas_buffer_new(%d, %d) failed.", size.width(), size.height());
191         return nullptr;
192     }
193
194     // By default EFL creates buffers without alpha.
195     ecore_evas_alpha_set(entry->canvas(), EINA_TRUE);
196
197     entry->m_edje = adoptRef(edje_object_add(ecore_evas_get(entry->canvas())));
198     ASSERT(entry->edje());
199
200     if (!setSourceGroupForEdjeObject(entry->edje(), themePath, toEdjeGroup(type)))
201         return nullptr;
202
203     entry->m_surface = createSurfaceForBackingStore(entry->canvas());
204     if (!entry->surface())
205         return nullptr;
206
207     evas_object_resize(entry->edje(), size.width(), size.height());
208     evas_object_show(entry->edje());
209
210     entry->type = type;
211     entry->size = size;
212
213     return entry.release();
214 }
215
216 void RenderThemeEfl::ThemePartCacheEntry::reuse(const String& themePath, FormType newType, const IntSize& newSize)
217 {
218     ASSERT(!themePath.isEmpty());
219
220     if (type != newType) {
221         type = newType;
222         if (!setSourceGroupForEdjeObject(edje(), themePath, toEdjeGroup(newType))) {
223             type = FormTypeLast; // Invalidate.
224             return;
225         }
226     }
227
228     if (size != newSize) {
229         size = newSize;
230         ecore_evas_resize(canvas(), newSize.width(), newSize.height());
231         evas_object_resize(edje(), newSize.width(), newSize.height());
232
233         m_surface = createSurfaceForBackingStore(canvas());
234         if (!surface()) {
235             type = FormTypeLast; // Invalidate;
236             return;
237         }
238     }
239 }
240
241 RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::getThemePartFromCache(FormType type, const IntSize& size)
242 {
243     void* data;
244     Eina_List* node;
245     Eina_List* reusableNode = 0;
246
247     // Look for the item in the cache.
248     EINA_LIST_FOREACH(m_partCache, node, data) {
249         ThemePartCacheEntry* cachedEntry = static_cast<ThemePartCacheEntry*>(data);
250         if (cachedEntry->size == size) {
251             if (cachedEntry->type == type) {
252                 // Found the right item, move it to the head of the list
253                 // and return it.
254                 m_partCache = eina_list_promote_list(m_partCache, node);
255                 return cachedEntry;
256             }
257             // We reuse in priority the last item in the list that has
258             // the requested size.
259             reusableNode = node;
260         }
261     }
262
263     if (eina_list_count(m_partCache) < RENDER_THEME_EFL_PART_CACHE_MAX) {
264         ThemePartCacheEntry* entry = ThemePartCacheEntry::create(themePath(), type, size).leakPtr();
265         if (entry)
266             m_partCache = eina_list_prepend(m_partCache, entry);
267
268         return entry;
269     }
270
271     // The cache is full, reuse the last item we found that had the
272     // requested size to avoid resizing. If there was none, reuse
273     // the last item of the list.
274     if (!reusableNode)
275         reusableNode = eina_list_last(m_partCache);
276
277     ThemePartCacheEntry* reusedEntry = static_cast<ThemePartCacheEntry*>(eina_list_data_get(reusableNode));
278     ASSERT(reusedEntry);
279     reusedEntry->reuse(themePath(), type, size);
280     m_partCache = eina_list_promote_list(m_partCache, reusableNode);
281
282     return reusedEntry;
283 }
284
285 void RenderThemeEfl::clearThemePartCache()
286 {
287     void* data;
288     EINA_LIST_FREE(m_partCache, data)
289         delete static_cast<ThemePartCacheEntry*>(data);
290
291 }
292
293 void RenderThemeEfl::applyEdjeStateFromForm(Evas_Object* object, ControlStates states)
294 {
295     const char *signals[] = { // keep in sync with WebCore/platform/ThemeTypes.h
296         "hovered",
297         "pressed",
298         "focused",
299         "enabled",
300         "checked",
301         "read-only",
302         "default",
303         "window-inactive",
304         "indeterminate",
305         "spinup"
306     };
307
308     edje_object_signal_emit(object, "reset", "");
309
310     for (size_t i = 0; i < WTF_ARRAY_LENGTH(signals); ++i) {
311         if (states & (1 << i))
312             edje_object_signal_emit(object, signals[i], "");
313     }
314 }
315
316 void RenderThemeEfl::applyEdjeRTLState(Evas_Object* edje, RenderObject* object, FormType type, const IntRect& rect)
317 {
318     if (type == SliderVertical || type == SliderHorizontal) {
319         if (!object->isSlider())
320             return; // probably have -webkit-appearance: slider..
321
322         RenderSlider* renderSlider = toRenderSlider(object);
323         HTMLInputElement* input = renderSlider->node()->toInputElement();
324         double valueRange = input->maximum() - input->minimum();
325
326         OwnPtr<Edje_Message_Float_Set> msg = adoptPtr(static_cast<Edje_Message_Float_Set*>(operator new (sizeof(Edje_Message_Float_Set) + sizeof(double))));
327         msg->count = 2;
328
329         // The first parameter of the message decides if the progress bar
330         // grows from the end of the slider or from the beginning. On vertical
331         // sliders, it should always be the same and will not be affected by
332         // text direction settings.
333         if (object->style()->direction() == RTL || type == SliderVertical)
334             msg->val[0] = 1;
335         else
336             msg->val[0] = 0;
337
338         msg->val[1] = (input->valueAsNumber() - input->minimum()) / valueRange;
339         edje_object_message_send(edje, EDJE_MESSAGE_FLOAT_SET, 0, msg.get());
340 #if ENABLE(PROGRESS_ELEMENT)
341     } else if (type == ProgressBar) {
342         RenderProgress* renderProgress = toRenderProgress(object);
343
344         int max = rect.width();
345         double value = renderProgress->position();
346
347         OwnPtr<Edje_Message_Float_Set> msg = adoptPtr(static_cast<Edje_Message_Float_Set*>(operator new (sizeof(Edje_Message_Float_Set) + sizeof(double))));
348         msg->count = 2;
349
350         if (object->style()->direction() == RTL)
351             msg->val[0] = (1.0 - value) * max;
352         else
353             msg->val[0] = 0;
354         msg->val[1] = value;
355         edje_object_message_send(edje, EDJE_MESSAGE_FLOAT_SET, 0, msg.get());
356 #else
357         UNUSED_PARAM(rect);
358 #endif
359     }
360 }
361
362 bool RenderThemeEfl::paintThemePart(RenderObject* object, FormType type, const PaintInfo& info, const IntRect& rect)
363 {
364     loadThemeIfNeeded();
365     _ASSERT_ON_RELEASE_RETURN_VAL(edje(), false, "Could not paint native HTML part due to missing theme.");
366
367     ThemePartCacheEntry* entry = getThemePartFromCache(type, rect.size());
368     if (!entry)
369         return false;
370
371     applyEdjeStateFromForm(entry->edje(), controlStatesForRenderer(object));
372     applyEdjeRTLState(entry->edje(), object, type, rect);
373
374     edje_object_calc_force(entry->edje());
375     edje_object_message_signal_process(entry->edje());
376     evas_render(ecore_evas_get(entry->canvas()));
377
378     cairo_t* cairo = info.context->platformContext()->cr();
379     ASSERT(cairo);
380
381     cairo_save(cairo);
382     cairo_set_source_surface(cairo, entry->surface(), rect.x(), rect.y());
383     cairo_paint_with_alpha(cairo, 1.0);
384     cairo_restore(cairo);
385
386     return false;
387 }
388
389 PassRefPtr<RenderTheme> RenderThemeEfl::create(Page* page)
390 {
391     return adoptRef(new RenderThemeEfl(page));
392 }
393
394 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
395 {
396     if (page)
397         return RenderThemeEfl::create(page);
398
399     static RenderTheme* fallback = RenderThemeEfl::create(0).leakRef();
400     return fallback;
401 }
402
403 static void applyColorCallback(void* data, Evas_Object*, const char* /* signal */, const char* colorClass)
404 {
405     RenderThemeEfl* that = static_cast<RenderThemeEfl*>(data);
406     that->setColorFromThemeClass(colorClass);
407     that->platformColorsDidChange(); // Triggers relayout.
408 }
409
410 static bool fillColorsFromEdjeClass(Evas_Object* o, const char* colorClass, Color* color1, Color* color2 = 0, Color* color3 = 0)
411 {
412     int r1, g1, b1, a1;
413     int r2, g2, b2, a2;
414     int r3, g3, b3, a3;
415
416     if (!edje_object_color_class_get(o, colorClass, &r1, &g1, &b1, &a1, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3))
417         return false;
418
419     if (color1)
420         color1->setRGB(makeRGBA(r1, g1, b1, a1));
421     if (color2)
422         color2->setRGB(makeRGBA(r2, g2, b2, a2));
423     if (color3)
424         color3->setRGB(makeRGBA(r3, g3, b3, a3));
425
426     return true;
427 }
428
429 void RenderThemeEfl::setColorFromThemeClass(const char* colorClass)
430 {
431     ASSERT(edje());
432
433     if (!strcmp("webkit/selection/foreground", colorClass))
434         m_supportsSelectionForegroundColor = fillColorsFromEdjeClass(edje(), colorClass, &m_activeSelectionForegroundColor, &m_inactiveSelectionForegroundColor);
435     else if (!strcmp("webkit/selection/background", colorClass))
436         fillColorsFromEdjeClass(edje(), colorClass, &m_activeSelectionBackgroundColor, &m_inactiveSelectionBackgroundColor);
437     else if (!strcmp("webkit/focus_ring", colorClass)) {
438         if (!fillColorsFromEdjeClass(edje(), colorClass, &m_focusRingColor))
439             return;
440
441         // platformFocusRingColor() is only used for the default theme (without page)
442         // The following is ugly, but no other way to do it unless we change it to use page themes as much as possible.
443         RenderTheme::setCustomFocusRingColor(m_focusRingColor);
444     }
445 }
446
447 void RenderThemeEfl::setThemePath(const String& newThemePath)
448 {
449     if (newThemePath == m_themePath)
450         return;
451
452     if (newThemePath.isEmpty()) {
453         EINA_LOG_CRIT("No valid theme defined, things will not work properly.");
454         return;
455     }
456
457     String oldThemePath = m_themePath;
458     m_themePath = newThemePath;
459
460     // Keep the consistence by restoring the previous theme path
461     // if we cannot load the new one.
462     if (!loadTheme())
463         m_themePath = oldThemePath;
464 }
465
466 String RenderThemeEfl::themePath() const
467 {
468 #ifndef NDEBUG
469     if (edje()) {
470         const char* path;
471         edje_object_file_get(edje(), &path, 0);
472         ASSERT(m_themePath == path);
473     }
474 #endif
475     return m_themePath;
476 }
477
478 bool RenderThemeEfl::loadTheme()
479 {
480     ASSERT(!m_themePath.isEmpty());
481
482     if (!canvas()) {
483         m_canvas = adoptPtr(ecore_evas_buffer_new(1, 1));
484         _ASSERT_ON_RELEASE_RETURN_VAL(canvas(), false,
485                 "Could not create canvas required by theme, things will not work properly.");
486     }
487
488     RefPtr<Evas_Object> o = adoptRef(edje_object_add(ecore_evas_get(canvas())));
489     _ASSERT_ON_RELEASE_RETURN_VAL(o, false, "Could not create new base Edje object.");
490
491     if (!setSourceGroupForEdjeObject(o.get(), m_themePath, "webkit/base"))
492         return false; // Keep current theme.
493
494     // Invalidate existing theme part cache.
495     if (edje())
496         clearThemePartCache();
497
498     // Set new loaded theme, and apply it.
499     m_edje = o;
500
501     edje_object_signal_callback_add(edje(), "color_class,set", "webkit/selection/foreground", applyColorCallback, this);
502     edje_object_signal_callback_add(edje(), "color_class,set", "webkit/selection/background", applyColorCallback, this);
503     edje_object_signal_callback_add(edje(), "color_class,set", "webkit/focus_ring", applyColorCallback, this);
504
505     applyPartDescriptionsFrom(m_themePath);
506
507     setColorFromThemeClass("webkit/selection/foreground");
508     setColorFromThemeClass("webkit/selection/background");
509     setColorFromThemeClass("webkit/focus_ring");
510
511     platformColorsDidChange(); // Schedules a relayout, do last.
512
513     return true;
514 }
515
516 void RenderThemeEfl::applyPartDescriptionFallback(ThemePartDesc* desc)
517 {
518     desc->min.setWidth(Length(0, Fixed));
519     desc->min.setHeight(Length(0, Fixed));
520
521     desc->max.setWidth(Length(0, Fixed));
522     desc->max.setHeight(Length(0, Fixed));
523
524     desc->padding = LengthBox(0, 0, 0, 0);
525 }
526
527 void RenderThemeEfl::applyPartDescription(Evas_Object* object, ThemePartDesc* desc)
528 {
529     Evas_Coord minw, minh, maxw, maxh;
530
531     edje_object_size_min_get(object, &minw, &minh);
532     if (!minw && !minh)
533         edje_object_size_min_calc(object, &minw, &minh);
534
535     desc->min.setWidth(Length(minw, Fixed));
536     desc->min.setHeight(Length(minh, Fixed));
537
538     edje_object_size_max_get(object, &maxw, &maxh);
539     desc->max.setWidth(Length(maxw, Fixed));
540     desc->max.setHeight(Length(maxh, Fixed));
541
542     if (!edje_object_part_exists(object, "text_confinement"))
543         desc->padding = LengthBox(0, 0, 0, 0);
544     else {
545         Evas_Coord px, py, pw, ph;
546         Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
547         int t, r, b, l;
548
549         if (minw > 0)
550             ow = minw;
551         else
552             ow = 100;
553         if (minh > 0)
554             oh = minh;
555         else
556             oh = 100;
557         if (maxw > 0 && ow > maxw)
558             ow = maxw;
559         if (maxh > 0 && oh > maxh)
560             oh = maxh;
561
562         evas_object_move(object, ox, oy);
563         evas_object_resize(object, ow, oh);
564         edje_object_calc_force(object);
565         edje_object_message_signal_process(object);
566         edje_object_part_geometry_get(object, "text_confinement", &px, &py, &pw, &ph);
567
568         t = py - oy;
569         b = (oh + oy) - (ph + py);
570
571         l = px - ox;
572         r = (ow + ox) - (pw + px);
573
574         desc->padding = LengthBox(t, r, b, l);
575     }
576 }
577
578 void RenderThemeEfl::applyPartDescriptionsFrom(const String& themePath)
579 {
580     RefPtr<Evas_Object> temp = adoptRef(edje_object_add(ecore_evas_get(canvas())));
581     _ASSERT_ON_RELEASE_RETURN(temp, "Could not create Edje object.");
582
583     for (size_t i = 0; i < FormTypeLast; i++) {
584         FormType type = static_cast<FormType>(i);
585         m_partDescs[i].type = type;
586         if (!setSourceGroupForEdjeObject(temp.get(), themePath, toEdjeGroup(type)))
587             applyPartDescriptionFallback(m_partDescs + i);
588         else
589             applyPartDescription(temp.get(), m_partDescs + i);
590     }
591 }
592
593 RenderThemeEfl::RenderThemeEfl(Page* page)
594     : RenderTheme()
595     , m_page(page)
596     , m_activeSelectionBackgroundColor(0, 0, 255)
597     , m_activeSelectionForegroundColor(Color::white)
598     , m_inactiveSelectionBackgroundColor(0, 0, 128)
599     , m_inactiveSelectionForegroundColor(200, 200, 200)
600     , m_focusRingColor(32, 32, 224, 224)
601     , m_sliderThumbColor(Color::darkGray)
602 #if ENABLE(VIDEO)
603     , m_mediaPanelColor(220, 220, 195) // light tannish color.
604     , m_mediaSliderColor(Color::white)
605 #endif
606     , m_supportsSelectionForegroundColor(false)
607     , m_partCache(0)
608 {
609 }
610
611 RenderThemeEfl::~RenderThemeEfl()
612 {
613     clearThemePartCache();
614 }
615
616 static bool supportsFocus(ControlPart appearance)
617 {
618     switch (appearance) {
619     case PushButtonPart:
620     case ButtonPart:
621     case TextFieldPart:
622     case TextAreaPart:
623     case SearchFieldPart:
624     case MenulistPart:
625     case RadioPart:
626     case CheckboxPart:
627     case SliderVerticalPart:
628     case SliderHorizontalPart:
629         return true;
630     default:
631         return false;
632     }
633 }
634
635 bool RenderThemeEfl::supportsFocusRing(const RenderStyle* style) const
636 {
637     return supportsFocus(style->appearance());
638 }
639
640 bool RenderThemeEfl::controlSupportsTints(const RenderObject* object) const
641 {
642     return isEnabled(object);
643 }
644
645 int RenderThemeEfl::baselinePosition(const RenderObject* object) const
646 {
647     if (!object->isBox())
648         return 0;
649
650     if (object->style()->appearance() == CheckboxPart
651     ||  object->style()->appearance() == RadioPart)
652         return toRenderBox(object)->marginTop() + toRenderBox(object)->height() - 3;
653
654     return RenderTheme::baselinePosition(object);
655 }
656
657 Color RenderThemeEfl::platformActiveSelectionBackgroundColor() const
658 {
659     loadThemeIfNeeded();
660     return m_activeSelectionBackgroundColor;
661 }
662
663 Color RenderThemeEfl::platformInactiveSelectionBackgroundColor() const
664 {
665     loadThemeIfNeeded();
666     return m_inactiveSelectionBackgroundColor;
667 }
668
669 Color RenderThemeEfl::platformActiveSelectionForegroundColor() const
670 {
671     loadThemeIfNeeded();
672     return m_activeSelectionForegroundColor;
673 }
674
675 Color RenderThemeEfl::platformInactiveSelectionForegroundColor() const
676 {
677     loadThemeIfNeeded();
678     return m_inactiveSelectionForegroundColor;
679 }
680
681 Color RenderThemeEfl::platformFocusRingColor() const
682 {
683     loadThemeIfNeeded();
684     return m_focusRingColor;
685 }
686
687 bool RenderThemeEfl::supportsSelectionForegroundColors() const
688 {
689     loadThemeIfNeeded();
690     return m_supportsSelectionForegroundColor;
691 }
692
693 bool RenderThemeEfl::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
694 {
695     if (object->style()->appearance() == SliderHorizontalPart)
696         paintThemePart(object, SliderHorizontal, info, rect);
697     else
698         paintThemePart(object, SliderVertical, info, rect);
699
700 #if ENABLE(DATALIST_ELEMENT)
701     paintSliderTicks(object, info, rect);
702 #endif
703
704     return false;
705 }
706
707 void RenderThemeEfl::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const
708 {
709     style->setBoxShadow(nullptr);
710 }
711
712 void RenderThemeEfl::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
713 {
714     RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
715     style->setBoxShadow(nullptr);
716 }
717
718 void RenderThemeEfl::adjustSliderThumbSize(RenderStyle* style, Element*) const
719 {
720     ControlPart part = style->appearance();
721     if (part == SliderThumbVerticalPart) {
722         style->setWidth(Length(sliderThumbHeight, Fixed));
723         style->setHeight(Length(sliderThumbWidth, Fixed));
724     } else if (part == SliderThumbHorizontalPart) {
725         style->setWidth(Length(sliderThumbWidth, Fixed));
726         style->setHeight(Length(sliderThumbHeight, Fixed));
727 #if ENABLE(VIDEO)
728     } else if (part == MediaSliderThumbPart) {
729         style->setWidth(Length(mediaSliderThumbWidth, Fixed));
730         style->setHeight(Length(mediaSliderThumbHeight, Fixed));
731 #endif
732     }
733 }
734
735 #if ENABLE(DATALIST_ELEMENT)
736 IntSize RenderThemeEfl::sliderTickSize() const
737 {
738     return IntSize(1, 6);
739 }
740
741 int RenderThemeEfl::sliderTickOffsetFromTrackCenter() const
742 {
743     static const int sliderTickOffset = -12;
744
745     return sliderTickOffset;
746 }
747
748 LayoutUnit RenderThemeEfl::sliderTickSnappingThreshold() const
749 {
750     // The same threshold value as the Chromium port.
751     return 5;
752 }
753 #endif
754
755 bool RenderThemeEfl::supportsDataListUI(const AtomicString& type) const
756 {
757 #if ENABLE(DATALIST_ELEMENT)
758     // FIXME: We need to support other types.
759     return type == InputTypeNames::range();
760 #else
761     UNUSED_PARAM(type);
762     return false;
763 #endif
764 }
765
766 bool RenderThemeEfl::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
767 {
768     if (object->style()->appearance() == SliderThumbHorizontalPart)
769         paintThemePart(object, SliderThumbHorizontal, info, rect);
770     else
771         paintThemePart(object, SliderThumbVertical, info, rect);
772
773     return false;
774 }
775
776 void RenderThemeEfl::adjustCheckboxStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
777 {
778     if (!m_page && element && element->document()->page()) {
779         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustCheckboxStyle(styleResolver, style, element);
780         return;
781     }
782
783     adjustSizeConstraints(style, CheckBox);
784
785     style->resetBorder();
786
787     const ThemePartDesc* desc = m_partDescs + (size_t)CheckBox;
788     if (style->width().value() < desc->min.width().value())
789         style->setWidth(desc->min.width());
790     if (style->height().value() < desc->min.height().value())
791         style->setHeight(desc->min.height());
792 }
793
794 bool RenderThemeEfl::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
795 {
796     return paintThemePart(object, CheckBox, info, rect);
797 }
798
799 void RenderThemeEfl::adjustRadioStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
800 {
801     if (!m_page && element && element->document()->page()) {
802         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustRadioStyle(styleResolver, style, element);
803         return;
804     }
805
806     adjustSizeConstraints(style, RadioButton);
807
808     style->resetBorder();
809
810     const ThemePartDesc* desc = m_partDescs + (size_t)RadioButton;
811     if (style->width().value() < desc->min.width().value())
812         style->setWidth(desc->min.width());
813     if (style->height().value() < desc->min.height().value())
814         style->setHeight(desc->min.height());
815 }
816
817 bool RenderThemeEfl::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
818 {
819     return paintThemePart(object, RadioButton, info, rect);
820 }
821
822 void RenderThemeEfl::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
823 {
824     if (!m_page && element && element->document()->page()) {
825         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustButtonStyle(styleResolver, style, element);
826         return;
827     }
828
829     // adjustSizeConstrains can make SquareButtonPart's size wrong (by adjusting paddings), so call it only for PushButtonPart and ButtonPart
830     if (style->appearance() == PushButtonPart || style->appearance() == ButtonPart)
831         adjustSizeConstraints(style, Button);
832 }
833
834 bool RenderThemeEfl::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
835 {
836     return paintThemePart(object, Button, info, rect);
837 }
838
839 void RenderThemeEfl::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
840 {
841     if (!m_page && element && element->document()->page()) {
842         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustMenuListStyle(styleResolver, style, element);
843         return;
844     }
845     adjustSizeConstraints(style, ComboBox);
846     style->resetBorder();
847     style->setWhiteSpace(PRE);
848
849     style->setLineHeight(RenderStyle::initialLineHeight());
850 }
851
852 bool RenderThemeEfl::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
853 {
854     return paintThemePart(object, ComboBox, info, rect);
855 }
856
857 void RenderThemeEfl::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
858 {
859     adjustMenuListStyle(styleResolver, style, element);
860 }
861
862 bool RenderThemeEfl::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
863 {
864     return paintMenuList(object, info, rect);
865 }
866
867 void RenderThemeEfl::adjustTextFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
868 {
869     if (!m_page && element && element->document()->page()) {
870         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustTextFieldStyle(styleResolver, style, element);
871         return;
872     }
873     adjustSizeConstraints(style, TextField);
874     style->resetBorder();
875 }
876
877 bool RenderThemeEfl::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
878 {
879     return paintThemePart(object, TextField, info, rect);
880 }
881
882 void RenderThemeEfl::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
883 {
884 }
885
886 bool RenderThemeEfl::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
887 {
888     return paintTextField(object, info, rect);
889 }
890
891 void RenderThemeEfl::adjustSearchFieldDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
892 {
893     if (!m_page && element && element->document()->page()) {
894         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldDecorationStyle(styleResolver, style, element);
895         return;
896     }
897     adjustSizeConstraints(style, SearchFieldDecoration);
898     style->resetBorder();
899     style->setWhiteSpace(PRE);
900 }
901
902 bool RenderThemeEfl::paintSearchFieldDecoration(RenderObject* object, const PaintInfo& info, const IntRect& rect)
903 {
904     return paintThemePart(object, SearchFieldDecoration, info, rect);
905 }
906
907 void RenderThemeEfl::adjustSearchFieldResultsButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
908 {
909     if (!m_page && element && element->document()->page()) {
910         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsButtonStyle(styleResolver, style, element);
911         return;
912     }
913     adjustSizeConstraints(style, SearchFieldResultsButton);
914     style->resetBorder();
915     style->setWhiteSpace(PRE);
916 }
917
918 bool RenderThemeEfl::paintSearchFieldResultsButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
919 {
920     return paintThemePart(object, SearchFieldResultsButton, info, rect);
921 }
922
923 void RenderThemeEfl::adjustSearchFieldResultsDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
924 {
925     if (!m_page && element && element->document()->page()) {
926         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsDecorationStyle(styleResolver, style, element);
927         return;
928     }
929     adjustSizeConstraints(style, SearchFieldResultsDecoration);
930     style->resetBorder();
931     style->setWhiteSpace(PRE);
932 }
933
934 bool RenderThemeEfl::paintSearchFieldResultsDecoration(RenderObject* object, const PaintInfo& info, const IntRect& rect)
935 {
936     return paintThemePart(object, SearchFieldResultsDecoration, info, rect);
937 }
938
939 void RenderThemeEfl::adjustSearchFieldCancelButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
940 {
941     if (!m_page && element && element->document()->page()) {
942         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldCancelButtonStyle(styleResolver, style, element);
943         return;
944     }
945     adjustSizeConstraints(style, SearchFieldCancelButton);
946     style->resetBorder();
947     style->setWhiteSpace(PRE);
948 }
949
950 bool RenderThemeEfl::paintSearchFieldCancelButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
951 {
952     return paintThemePart(object, SearchFieldCancelButton, info, rect);
953 }
954
955 void RenderThemeEfl::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
956 {
957     if (!m_page && element && element->document()->page()) {
958         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldStyle(styleResolver, style, element);
959         return;
960     }
961     adjustSizeConstraints(style, SearchField);
962     style->resetBorder();
963     style->setWhiteSpace(PRE);
964 }
965
966 bool RenderThemeEfl::paintSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
967 {
968     return paintThemePart(object, SearchField, info, rect);
969 }
970
971 void RenderThemeEfl::adjustInnerSpinButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
972 {
973     if (!m_page && element && element->document()->page()) {
974         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustInnerSpinButtonStyle(styleResolver, style, element);
975         return;
976     }
977     adjustSizeConstraints(style, Spinner);
978 }
979
980 bool RenderThemeEfl::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
981 {
982     return paintThemePart(object, Spinner, info, rect);
983 }
984
985 void RenderThemeEfl::setDefaultFontSize(int size)
986 {
987     defaultFontSize = size;
988 }
989
990 void RenderThemeEfl::systemFont(int, FontDescription& fontDescription) const
991 {
992     // It was called by RenderEmbeddedObject::paintReplaced to render alternative string.
993     // To avoid cairo_error while rendering, fontDescription should be passed.
994     DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Sans")));
995     float fontSize = defaultFontSize;
996
997     fontDescription.firstFamily().setFamily(fontFace);
998     fontDescription.setSpecifiedSize(fontSize);
999     fontDescription.setIsAbsoluteSize(true);
1000     fontDescription.setGenericFamily(FontDescription::NoFamily);
1001     fontDescription.setWeight(FontWeightNormal);
1002     fontDescription.setItalic(false);
1003 }
1004
1005 #if ENABLE(PROGRESS_ELEMENT)
1006 void RenderThemeEfl::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
1007 {
1008     style->setBoxShadow(nullptr);
1009 }
1010
1011 double RenderThemeEfl::animationRepeatIntervalForProgressBar(RenderProgress*) const
1012 {
1013     return progressAnimationInterval;
1014 }
1015
1016 double RenderThemeEfl::animationDurationForProgressBar(RenderProgress*) const
1017 {
1018     return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth;
1019 }
1020
1021 bool RenderThemeEfl::paintProgressBar(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1022 {
1023     if (!object->isProgress())
1024         return true;
1025
1026     return paintThemePart(object, ProgressBar, info, rect);
1027 }
1028 #endif
1029
1030 #if ENABLE(VIDEO)
1031 bool RenderThemeEfl::emitMediaButtonSignal(FormType formType, MediaControlElementType mediaElementType, const IntRect& rect)
1032 {
1033     loadThemeIfNeeded();
1034     _ASSERT_ON_RELEASE_RETURN_VAL(edje(), false, "Could not paint native HTML part due to missing theme.");
1035
1036     ThemePartCacheEntry* entry = getThemePartFromCache(formType, rect.size());
1037     _ASSERT_ON_RELEASE_RETURN_VAL(entry, false, "Could not paint native HTML part due to missing theme part.");
1038
1039     if (mediaElementType == MediaPlayButton)
1040         edje_object_signal_emit(entry->edje(), "play", "");
1041     else if (mediaElementType == MediaPauseButton)
1042         edje_object_signal_emit(entry->edje(), "pause", "");
1043     else if (mediaElementType == MediaMuteButton)
1044         edje_object_signal_emit(entry->edje(), "mute", "");
1045     else if (mediaElementType == MediaUnMuteButton)
1046         edje_object_signal_emit(entry->edje(), "sound", "");
1047     else if (mediaElementType == MediaSeekForwardButton)
1048         edje_object_signal_emit(entry->edje(), "seekforward", "");
1049     else if (mediaElementType == MediaSeekBackButton)
1050         edje_object_signal_emit(entry->edje(), "seekbackward", "");
1051     else if (mediaElementType == MediaEnterFullscreenButton)
1052         edje_object_signal_emit(entry->edje(), "fullscreen_enter", "");
1053     else if (mediaElementType == MediaExitFullscreenButton)
1054         edje_object_signal_emit(entry->edje(), "fullscreen_exit", "");
1055 #if ENABLE(VIDEO_TRACK)
1056     else if (mediaElementType == MediaShowClosedCaptionsButton)
1057         edje_object_signal_emit(entry->edje(), "show_captions", "");
1058     else if (mediaElementType == MediaHideClosedCaptionsButton)
1059         edje_object_signal_emit(entry->edje(), "hide_captions", "");
1060 #endif
1061     else
1062         return false;
1063
1064     return true;
1065 }
1066
1067 String RenderThemeEfl::extraMediaControlsStyleSheet()
1068 {
1069     return String(mediaControlsEflUserAgentStyleSheet, sizeof(mediaControlsEflUserAgentStyleSheet));
1070 }
1071
1072 #if ENABLE(FULLSCREEN_API)
1073 String RenderThemeEfl::extraFullScreenStyleSheet()
1074 {
1075     return String(mediaControlsEflFullscreenUserAgentStyleSheet, sizeof(mediaControlsEflFullscreenUserAgentStyleSheet));
1076 }
1077 #endif
1078
1079 String RenderThemeEfl::formatMediaControlsCurrentTime(float currentTime, float duration) const
1080 {
1081     return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration);
1082 }
1083
1084 bool RenderThemeEfl::hasOwnDisabledStateHandlingFor(ControlPart part) const
1085 {
1086     return (part != MediaMuteButtonPart);
1087 }
1088
1089 bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1090 {
1091     Node* mediaNode = object->node() ? object->node()->shadowHost() : 0;
1092     if (!mediaNode)
1093         mediaNode = object->node();
1094     if (!mediaNode || !mediaNode->isElementNode() || !static_cast<Element*>(mediaNode)->isMediaElement())
1095         return false;
1096
1097     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1098     if (!emitMediaButtonSignal(FullScreenButton, mediaElement->isFullscreen() ? MediaExitFullscreenButton : MediaEnterFullscreenButton, rect))
1099         return false;
1100
1101     return paintThemePart(object, FullScreenButton, info, rect);
1102 }
1103
1104 bool RenderThemeEfl::paintMediaMuteButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1105 {
1106     Node* mediaNode = object->node() ? object->node()->shadowHost() : 0;
1107     if (!mediaNode)
1108         mediaNode = object->node();
1109     if (!mediaNode || !mediaNode->isElementNode() || !static_cast<Element*>(mediaNode)->isMediaElement())
1110         return false;
1111
1112     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1113
1114     if (!emitMediaButtonSignal(MuteUnMuteButton, mediaElement->muted() ? MediaMuteButton : MediaUnMuteButton, rect))
1115         return false;
1116
1117     return paintThemePart(object, MuteUnMuteButton, info, rect);
1118 }
1119
1120 bool RenderThemeEfl::paintMediaPlayButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1121 {
1122     Node* node = object->node();
1123     if (!node || !node->isMediaControlElement())
1124         return false;
1125
1126     if (!emitMediaButtonSignal(PlayPauseButton, mediaControlElementType(node), rect))
1127         return false;
1128
1129     return paintThemePart(object, PlayPauseButton, info, rect);
1130 }
1131
1132 bool RenderThemeEfl::paintMediaSeekBackButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1133 {
1134     Node* node = object->node();
1135     if (!node || !node->isMediaControlElement())
1136         return 0;
1137
1138     if (!emitMediaButtonSignal(SeekBackwardButton, mediaControlElementType(node), rect))
1139         return false;
1140
1141     return paintThemePart(object, SeekBackwardButton, info, rect);
1142 }
1143
1144 bool RenderThemeEfl::paintMediaSeekForwardButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1145 {
1146     Node* node = object->node();
1147     if (!node || !node->isMediaControlElement())
1148         return 0;
1149
1150     if (!emitMediaButtonSignal(SeekForwardButton, mediaControlElementType(node), rect))
1151         return false;
1152
1153     return paintThemePart(object, SeekForwardButton, info, rect);
1154 }
1155
1156 bool RenderThemeEfl::paintMediaSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1157 {
1158     GraphicsContext* context = info.context;
1159
1160     context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1161     context->fillRect(FloatRect(IntRect(rect.x(), rect.y() + (rect.height() - mediaSliderHeight) / 2,
1162                                         rect.width(), mediaSliderHeight)), m_mediaSliderColor, ColorSpaceDeviceRGB);
1163
1164     RenderStyle* style = object->style();
1165     HTMLMediaElement* mediaElement = toParentMediaElement(object);
1166
1167     if (!mediaElement)
1168         return false;
1169
1170     // Draw the buffered ranges. This code is highly inspired from
1171     // Chrome for the gradient code.
1172     float mediaDuration = mediaElement->duration();
1173     RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
1174     IntRect trackRect = rect;
1175     int totalWidth = trackRect.width();
1176
1177     trackRect.inflate(-style->borderLeftWidth());
1178     context->save();
1179     context->setStrokeStyle(NoStroke);
1180
1181     for (unsigned index = 0; index < timeRanges->length(); ++index) {
1182         float start = timeRanges->start(index, IGNORE_EXCEPTION);
1183         float end = timeRanges->end(index, IGNORE_EXCEPTION);
1184         int width = ((end - start) * totalWidth) / mediaDuration;
1185         IntRect rangeRect;
1186         if (!index) {
1187             rangeRect = trackRect;
1188             rangeRect.setWidth(width);
1189         } else {
1190             rangeRect.setLocation(IntPoint(trackRect.x() + start / mediaDuration* totalWidth, trackRect.y()));
1191             rangeRect.setSize(IntSize(width, trackRect.height()));
1192         }
1193
1194         // Don't bother drawing empty range.
1195         if (rangeRect.isEmpty())
1196             continue;
1197
1198         IntPoint sliderTopLeft = rangeRect.location();
1199         IntPoint sliderTopRight = sliderTopLeft;
1200         sliderTopRight.move(0, rangeRect.height());
1201
1202         context->fillRect(FloatRect(rangeRect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1203     }
1204     context->restore();
1205     return true;
1206 }
1207
1208 bool RenderThemeEfl::paintMediaSliderThumb(RenderObject*, const PaintInfo& info, const IntRect& rect)
1209 {
1210     IntSize thumbRect(3, 3);
1211     info.context->fillRoundedRect(rect, thumbRect, thumbRect, thumbRect, thumbRect, m_sliderThumbColor, ColorSpaceDeviceRGB);
1212     return true;
1213 }
1214
1215 bool RenderThemeEfl::paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&)
1216 {
1217     notImplemented();
1218     return false;
1219 }
1220
1221 bool RenderThemeEfl::paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&)
1222 {
1223     notImplemented();
1224     return false;
1225 }
1226
1227 bool RenderThemeEfl::paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&)
1228 {
1229     notImplemented();
1230     return false;
1231 }
1232
1233 bool RenderThemeEfl::paintMediaCurrentTime(RenderObject*, const PaintInfo& info, const IntRect& rect)
1234 {
1235     info.context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1236     return true;
1237 }
1238 #endif
1239
1240 #if ENABLE(VIDEO_TRACK)
1241 bool RenderThemeEfl::supportsClosedCaptioning() const
1242 {
1243     return true;
1244 }
1245
1246 bool RenderThemeEfl::paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1247 {
1248     Node* mediaNode = object->node() ? object->node()->shadowHost() : 0;
1249     if (!mediaNode)
1250         mediaNode = object->node();
1251     if (!mediaNode || (!mediaNode->hasTagName(videoTag)))
1252         return false;
1253
1254     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1255     if (!emitMediaButtonSignal(ToggleCaptionsButton, mediaElement->webkitClosedCaptionsVisible() ? MediaShowClosedCaptionsButton : MediaHideClosedCaptionsButton, rect))
1256         return false;
1257
1258     return paintThemePart(object, ToggleCaptionsButton, info, rect);
1259 }
1260 #endif
1261
1262 #undef _ASSERT_ON_RELEASE_RETURN
1263 #undef _ASSERT_ON_RELEASE_RETURN_VAL
1264
1265 }