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