Fix the text_box sticking out from combo_box.
[framework/web/webkit-efl.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 "GraphicsContext.h"
33 #include "HTMLInputElement.h"
34 #include "NotImplemented.h"
35 #include "Page.h"
36 #include "PaintInfo.h"
37 #include "PlatformContextCairo.h"
38 #include "RenderBox.h"
39 #include "RenderObject.h"
40 #include "RenderProgress.h"
41 #include "RenderSlider.h"
42 #include "UserAgentStyleSheets.h"
43
44 #include <Ecore_Evas.h>
45 #include <Edje.h>
46 #include <wtf/text/CString.h>
47 #include <wtf/text/WTFString.h>
48
49 #if ENABLE(VIDEO)
50 #include "HTMLMediaElement.h"
51 #include "HTMLNames.h"
52 #include "TimeRanges.h"
53 #endif
54
55 namespace WebCore {
56 #if ENABLE(VIDEO)
57 using namespace HTMLNames;
58 #endif
59
60 // TODO: change from object count to ecore_evas size (bytes)
61 // TODO: as objects are webpage/user defined and they can be very large.
62 #define RENDER_THEME_EFL_PART_CACHE_MAX 32
63
64 #if ENABLE(TIZEN_THEME_STYLE_WORKAROUND)
65 //EFL theme should set control font sizes, in case the font size goes beyond certain value.
66 #define RENDER_THEME_EFL_CONTROL_FONT_SIZE 12
67 #endif
68
69 // Initialize default font size.
70 #if ENABLE(TIZEN_SYSTEM_FONT)
71 float RenderThemeEfl::defaultFontSize = 13.0f;
72 #else
73 float RenderThemeEfl::defaultFontSize = 16.0f;
74 #endif
75
76 static const float minCancelButtonSize = 5;
77 static const float maxCancelButtonSize = 21;
78
79 // Constants for progress tag animation.
80 // These values have been copied from RenderThemeGtk.cpp
81 static const int progressAnimationFrames = 10;
82 static const double progressAnimationInterval = 0.125;
83
84 static const int sliderThumbWidth = 29;
85 static const int sliderThumbHeight = 11;
86
87 #if ENABLE(VIDEO)
88 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
89 static const int mediaSliderThumbWidth = 14;
90 static const int mediaSliderThumbHeight = 14;
91 static const int mediaSliderFullScreenThumbWidth = 30;
92 static const int mediaSliderFullScreenThumbHeight = 30;
93 static const int mediaSliderHeight = 4;
94 #else
95 static const int mediaSliderThumbWidth = 12;
96 static const int mediaSliderThumbHeight = 12;
97 static const int mediaSliderHeight = 14;
98 #endif
99 #endif
100
101 void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) const
102 {
103     const struct ThemePartDesc* desc = m_partDescs + (size_t)type;
104
105     if (style->minWidth().isIntrinsic())
106         style->setMinWidth(desc->min.width());
107     if (style->minHeight().isIntrinsic())
108         style->setMinHeight(desc->min.height());
109
110     if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto())
111         style->setMaxWidth(desc->max.width());
112     if (desc->max.height().value() > 0 && style->maxHeight().isIntrinsicOrAuto())
113         style->setMaxHeight(desc->max.height());
114
115     style->setPaddingTop(desc->padding.top());
116     style->setPaddingBottom(desc->padding.bottom());
117     style->setPaddingLeft(desc->padding.left());
118     style->setPaddingRight(desc->padding.right());
119 }
120
121 bool RenderThemeEfl::themePartCacheEntryReset(struct ThemePartCacheEntry* entry, FormType type)
122 {
123     const char *file, *group;
124
125     ASSERT(entry);
126     ASSERT(m_edje);
127
128     edje_object_file_get(m_edje, &file, 0);
129     group = edjeGroupFromFormType(type);
130     ASSERT(file);
131     ASSERT(group);
132
133     if (!edje_object_file_set(entry->o, file, group)) {
134         Edje_Load_Error err = edje_object_load_error_get(entry->o);
135         const char *errmsg = edje_load_error_str(err);
136         EINA_LOG_ERR("Could not load '%s' from theme %s: %s",
137                      group, file, errmsg);
138         return false;
139     }
140     return true;
141 }
142
143 bool RenderThemeEfl::themePartCacheEntrySurfaceCreate(struct ThemePartCacheEntry* entry)
144 {
145     int w, h;
146     cairo_status_t status;
147
148     ASSERT(entry);
149     ASSERT(entry->ee);
150
151     ecore_evas_geometry_get(entry->ee, 0, 0, &w, &h);
152     ASSERT(w > 0);
153     ASSERT(h > 0);
154
155     entry->surface = cairo_image_surface_create_for_data((unsigned char *)ecore_evas_buffer_pixels_get(entry->ee),
156                                                       CAIRO_FORMAT_ARGB32, w, h, w * 4);
157     status = cairo_surface_status(entry->surface);
158     if (status != CAIRO_STATUS_SUCCESS) {
159         EINA_LOG_ERR("Could not create cairo surface: %s",
160                      cairo_status_to_string(status));
161         return false;
162     }
163
164     return true;
165 }
166
167 bool RenderThemeEfl::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 // allocate a new entry and fill it with edje group
178 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartNew(FormType type, const IntSize& size)
179 {
180     if (isFormElementTooLargeToDisplay(size)) {
181         EINA_LOG_ERR("cannot render an element of size %dx%d", size.width(), size.height());
182         return 0;
183     }
184
185     ThemePartCacheEntry* entry = new ThemePartCacheEntry;
186     if (!entry) {
187         EINA_LOG_ERR("could not allocate ThemePartCacheEntry.");
188         return 0;
189     }
190
191     entry->ee = ecore_evas_buffer_new(size.width(), size.height());
192     if (!entry->ee) {
193         EINA_LOG_ERR("ecore_evas_buffer_new(%d, %d) failed.",
194                      size.width(), size.height());
195         delete entry;
196         return 0;
197     }
198
199     // By default EFL creates buffers without alpha.
200     ecore_evas_alpha_set(entry->ee, EINA_TRUE);
201
202     entry->o = edje_object_add(ecore_evas_get(entry->ee));
203     ASSERT(entry->o);
204     if (!themePartCacheEntryReset(entry, type)) {
205         evas_object_del(entry->o);
206         ecore_evas_free(entry->ee);
207         delete entry;
208         return 0;
209     }
210
211     if (!themePartCacheEntrySurfaceCreate(entry)) {
212         evas_object_del(entry->o);
213         ecore_evas_free(entry->ee);
214         delete entry;
215         return 0;
216     }
217
218     evas_object_resize(entry->o, size.width(), size.height());
219     evas_object_show(entry->o);
220
221     entry->type = type;
222     entry->size = size;
223
224     m_partCache.prepend(entry);
225     return entry;
226 }
227
228 // just change the edje group and return the same entry
229 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartReset(FormType type, struct RenderThemeEfl::ThemePartCacheEntry* entry)
230 {
231     if (!themePartCacheEntryReset(entry, type)) {
232         entry->type = FormTypeLast; // invalidate
233         m_partCache.append(entry);
234         return 0;
235     }
236     entry->type = type;
237     m_partCache.prepend(entry);
238     return entry;
239 }
240
241 // resize entry and reset it
242 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartResizeAndReset(FormType type, const IntSize& size, struct RenderThemeEfl::ThemePartCacheEntry* entry)
243 {
244     cairo_surface_finish(entry->surface);
245
246     entry->size = size;
247     ecore_evas_resize(entry->ee, size.width(), size.height());
248     evas_object_resize(entry->o, size.width(), size.height());
249
250     if (!themePartCacheEntrySurfaceCreate(entry)) {
251         evas_object_del(entry->o);
252         ecore_evas_free(entry->ee);
253         delete entry;
254         return 0;
255     }
256
257     return cacheThemePartReset(type, entry);
258 }
259
260 // general purpose get (will create, reuse and all)
261 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartGet(FormType type, const IntSize& size)
262 {
263     Vector<struct ThemePartCacheEntry *>::iterator itr, end;
264     struct ThemePartCacheEntry *ce_last_size = 0;
265     int i, idxLastSize = -1;
266
267     itr = m_partCache.begin();
268     end = m_partCache.end();
269     for (i = 0; itr != end; i++, itr++) {
270         struct ThemePartCacheEntry *entry = *itr;
271         if (entry->size == size) {
272             if (entry->type == type)
273                 return entry;
274             ce_last_size = entry;
275             idxLastSize = i;
276         }
277     }
278
279     if (m_partCache.size() < RENDER_THEME_EFL_PART_CACHE_MAX)
280         return cacheThemePartNew(type, size);
281
282     if (ce_last_size && ce_last_size != m_partCache.first()) {
283         m_partCache.remove(idxLastSize);
284         return cacheThemePartReset(type, ce_last_size);
285     }
286
287     ThemePartCacheEntry* entry = m_partCache.last();
288     m_partCache.removeLast();
289     return cacheThemePartResizeAndReset(type, size, entry);
290 }
291
292 void RenderThemeEfl::cacheThemePartFlush()
293 {
294     Vector<struct ThemePartCacheEntry *>::iterator itr, end;
295
296     itr = m_partCache.begin();
297     end = m_partCache.end();
298     for (; itr != end; itr++) {
299         struct ThemePartCacheEntry *entry = *itr;
300         cairo_surface_destroy(entry->surface);
301         evas_object_del(entry->o);
302         ecore_evas_free(entry->ee);
303         delete entry;
304     }
305     m_partCache.clear();
306 }
307
308 void RenderThemeEfl::applyEdjeStateFromForm(Evas_Object* object, ControlStates states)
309 {
310     const char *signals[] = { // keep in sync with WebCore/platform/ThemeTypes.h
311         "hovered",
312         "pressed",
313         "focused",
314         "enabled",
315         "checked",
316         "read-only",
317         "default",
318         "window-inactive",
319         "indeterminate",
320         "spinup"
321     };
322
323     edje_object_signal_emit(object, "reset", "");
324
325     for (size_t i = 0; i < WTF_ARRAY_LENGTH(signals); ++i) {
326         if (states & (1 << i))
327             edje_object_signal_emit(object, signals[i], "");
328     }
329 }
330
331 bool RenderThemeEfl::paintThemePart(RenderObject* object, FormType type, const PaintInfo& info, const IntRect& rect)
332 {
333     ThemePartCacheEntry* entry;
334     Eina_List* updates;
335     cairo_t* cairo;
336
337     ASSERT(m_canvas);
338     ASSERT(m_edje);
339
340 #if ENABLE(TIZEN_THEME_SCALE_SUPPORT)
341     float themeScaleValue = m_partDescs[type].scale;
342     IntSize scaledEntrySize(rect.size());
343     scaledEntrySize.scale(themeScaleValue);
344     entry = cacheThemePartGet(type, scaledEntrySize);
345 #else
346     entry = cacheThemePartGet(type, rect.size());
347 #endif
348     if (!entry)
349         return false;
350
351     applyEdjeStateFromForm(entry->o, controlStatesForRenderer(object));
352     if (object && object->hasBackground() && object->style()->visitedDependentColor(CSSPropertyBackgroundColor) != Color::white)
353         edje_object_signal_emit(entry->o, "bg_styled", "");
354     cairo = info.context->platformContext()->cr();
355     ASSERT(cairo);
356
357     // Currently, only sliders needs this message; if other widget ever needs special
358     // treatment, move them to special functions.
359     if (type == SliderVertical || type == SliderHorizontal) {
360         RenderSlider* renderSlider = toRenderSlider(object);
361         HTMLInputElement* input = renderSlider->node()->toInputElement();
362         if (!input)
363             return false;
364         double valueRange = input->maximum() - input->minimum();
365
366         OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
367         Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
368         msg->count = 2;
369
370         // The first parameter of the message decides if the progress bar
371         // grows from the end of the slider or from the beginning. On vertical
372         // sliders, it should always be the same and will not be affected by
373         // text direction settings.
374         if (object->style()->direction() == RTL || type == SliderVertical)
375             msg->val[0] = 1;
376         else
377             msg->val[0] = 0;
378
379         msg->val[1] = (input->valueAsNumber() - input->minimum()) / valueRange;
380         edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
381 #if ENABLE(PROGRESS_ELEMENT)
382     } else if (type == ProgressBar) {
383         RenderProgress* renderProgress = toRenderProgress(object);
384         int max;
385         double value;
386
387         max = rect.width();
388         value = renderProgress->position();
389
390         OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
391         Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
392         msg->count = 2;
393         if (object->style()->direction() == RTL)
394             msg->val[0] = (1.0 - value) * max;
395         else
396             msg->val[0] = 0;
397         msg->val[1] = value;
398         edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
399 #endif
400     }
401
402     edje_object_calc_force(entry->o);
403     edje_object_message_signal_process(entry->o);
404     updates = evas_render_updates(ecore_evas_get(entry->ee));
405     evas_render_updates_free(updates);
406
407     cairo_save(cairo);
408
409 #if ENABLE(TIZEN_THEME_SCALE_SUPPORT)
410     cairo_matrix_t matrix;
411     cairo_get_matrix(cairo, &matrix);
412     matrix.xx = matrix.xx / themeScaleValue;
413     matrix.yy = matrix.yy / themeScaleValue;
414     cairo_set_matrix(cairo, &matrix);
415
416     cairo_set_source_surface(cairo, entry->surface, rect.x() * themeScaleValue, rect.y() * themeScaleValue);
417 #else
418     cairo_set_source_surface(cairo, entry->surface, rect.x(), rect.y());
419 #endif
420     cairo_paint_with_alpha(cairo, 1.0);
421     cairo_restore(cairo);
422
423     return false;
424 }
425
426 PassRefPtr<RenderTheme> RenderThemeEfl::create(Page* page)
427 {
428     return adoptRef(new RenderThemeEfl(page));
429 }
430
431 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
432 {
433     if (page)
434         return RenderThemeEfl::create(page);
435
436     static RenderTheme* fallback = RenderThemeEfl::create(0).leakRef();
437     return fallback;
438 }
439
440 static void renderThemeEflColorClassSelectionForeground(void* data, Evas_Object* object, const char* signal, const char* source)
441 {
442     RenderThemeEfl* that = static_cast<RenderThemeEfl *>(data);
443     int fr, fg, fb, fa, br, bg, bb, ba;
444
445     if (!edje_object_color_class_get(object, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0))
446         return;
447
448     that->setSelectionForegroundColor(fr, fg, fb, fa, br, bg, bb, ba);
449 }
450
451 static void renderThemeEflColorClassSelectionBackground(void* data, Evas_Object* object, const char* signal, const char* source)
452 {
453     RenderThemeEfl* that = static_cast<RenderThemeEfl *>(data);
454     int fr, fg, fb, fa, br, bg, bb, ba;
455
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->setSelectionBackgroundColor(fr, fg, fb, fa, br, bg, bb, ba);
460 }
461
462 static void renderThemeEflColorClassFocusRing(void* data, Evas_Object* object, const char* signal, const char* source)
463 {
464     RenderThemeEfl* that = static_cast<RenderThemeEfl *>(data);
465     int fr, fg, fb, fa;
466
467     if (!edje_object_color_class_get(object, source, &fr, &fg, &fb, &fa, 0, 0, 0, 0, 0, 0, 0, 0))
468         return;
469
470     that->setFocusRingColor(fr, fg, fb, fa);
471 }
472
473 void RenderThemeEfl::setThemePath(const String& path)
474 {
475     if (path == m_themePath)
476         return;
477
478     m_themePath = path;
479     themeChanged();
480 }
481
482 void RenderThemeEfl::createCanvas()
483 {
484     ASSERT(!m_canvas);
485     m_canvas = ecore_evas_buffer_new(1, 1);
486     ASSERT(m_canvas);
487 }
488
489 void RenderThemeEfl::createEdje()
490 {
491     ASSERT(!m_edje);
492     if (m_themePath.isEmpty())
493         EINA_LOG_ERR("No theme defined, unable to set RenderThemeEfl.");
494     else {
495         m_edje = edje_object_add(ecore_evas_get(m_canvas));
496         if (!m_edje)
497             EINA_LOG_ERR("Could not create base edje object.");
498         else if (!edje_object_file_set(m_edje, m_themePath.utf8().data(), "webkit/base")) {
499             Edje_Load_Error err = edje_object_load_error_get(m_edje);
500             const char* errmsg = edje_load_error_str(err);
501             EINA_LOG_ERR("Could not load 'webkit/base' from theme %s: %s",
502                          m_themePath.utf8().data(), errmsg);
503             evas_object_del(m_edje);
504             m_edje = 0;
505         } else {
506 #define CONNECT(cc, func)                                               \
507             edje_object_signal_callback_add(m_edje, "color_class,set",  \
508                                             "webkit/"cc, func, this)
509
510             CONNECT("selection/foreground",
511                     renderThemeEflColorClassSelectionForeground);
512             CONNECT("selection/background",
513                     renderThemeEflColorClassSelectionBackground);
514             CONNECT("focus_ring", renderThemeEflColorClassFocusRing);
515 #undef CONNECT
516         }
517     }
518 }
519
520 void RenderThemeEfl::applyEdjeColors()
521 {
522     int fr, fg, fb, fa, br, bg, bb, ba;
523     ASSERT(m_edje);
524 #define COLOR_GET(cls)                                                  \
525     edje_object_color_class_get(m_edje, "webkit/"cls,                   \
526                                 &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, \
527                                 0, 0, 0, 0)
528
529     if (COLOR_GET("selection/foreground")) {
530         m_supportsSelectionForegroundColors = true;
531         m_activeSelectionForegroundColor = Color(fr, fg, fb, fa);
532         m_inactiveSelectionForegroundColor = Color(br, bg, bb, ba);
533     }
534     if (COLOR_GET("selection/background")) {
535         m_inactiveSelectionBackgroundColor = Color(fr, fg, fb, fa);
536         m_activeSelectionBackgroundColor = Color(br, bg, bb, ba);
537     }
538     if (COLOR_GET("focus_ring")) {
539         m_focusRingColor = Color(fr, fg, fb, fa);
540         // webkit just use platformFocusRingColor() for default theme (without page)
541         // this is ugly, but no other way to do it unless we change
542         // it to use page themes as much as possible.
543         RenderTheme::setCustomFocusRingColor(m_focusRingColor);
544     }
545 #undef COLOR_GET
546     platformColorsDidChange();
547 }
548
549 void RenderThemeEfl::applyPartDescriptionFallback(struct ThemePartDesc* desc)
550 {
551     desc->min.setWidth(Length(0, Fixed));
552     desc->min.setHeight(Length(0, Fixed));
553
554     desc->max.setWidth(Length(0, Fixed));
555     desc->max.setHeight(Length(0, Fixed));
556
557     desc->padding = LengthBox(0, 0, 0, 0);
558 }
559
560 void RenderThemeEfl::applyPartDescription(Evas_Object* object, struct ThemePartDesc* desc)
561 {
562     Evas_Coord minw, minh, maxw, maxh;
563
564 #if ENABLE(TIZEN_THEME_SCALE_SUPPORT)
565     const char* scale = edje_object_data_get(object, "scale");
566
567     if (scale)
568         desc->scale = atof(scale);
569     else
570         desc->scale = 1;
571 #endif
572
573     edje_object_size_min_get(object, &minw, &minh);
574     if (!minw && !minh)
575         edje_object_size_min_calc(object, &minw, &minh);
576
577 #if ENABLE(TIZEN_THEME_SCALE_SUPPORT)
578     minw /= desc->scale;
579     minh /= desc->scale;
580 #endif
581     desc->min.setWidth(Length(minw, Fixed));
582     desc->min.setHeight(Length(minh, Fixed));
583
584 #if ENABLE(TIZEN_THEME_SCALE_SUPPORT)
585     maxw /= desc->scale;
586     maxh /= desc->scale;
587 #endif
588     edje_object_size_max_get(object, &maxw, &maxh);
589     desc->max.setWidth(Length(maxw, Fixed));
590     desc->max.setHeight(Length(maxh, Fixed));
591
592     if (!edje_object_part_exists(object, "text_confinement"))
593         desc->padding = LengthBox(0, 0, 0, 0);
594     else {
595         Evas_Coord px, py, pw, ph;
596         Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
597         int t, r, b, l;
598
599         if (minw > 0)
600             ow = minw;
601         else
602             ow = 100;
603         if (minh > 0)
604             oh = minh;
605         else
606             oh = 100;
607         if (maxw > 0 && ow > maxw)
608             ow = maxw;
609         if (maxh > 0 && oh > maxh)
610             oh = maxh;
611
612         evas_object_move(object, ox, oy);
613         evas_object_resize(object, ow, oh);
614         edje_object_calc_force(object);
615         edje_object_message_signal_process(object);
616         edje_object_part_geometry_get(object, "text_confinement", &px, &py, &pw, &ph);
617
618         t = py - oy;
619         b = (oh + oy) - (ph + py);
620
621         l = px - ox;
622         r = (ow + ox) - (pw + px);
623
624         desc->padding = LengthBox(t, r, b, l);
625     }
626 }
627
628 const char* RenderThemeEfl::edjeGroupFromFormType(FormType type) const
629 {
630     static const char* groups[] = {
631 #define W(n) "webkit/widget/"n
632         W("button"),
633         W("radio"),
634         W("entry"),
635         W("checkbox"),
636         W("combo"),
637 #if ENABLE(PROGRESS_ELEMENT)
638         W("progressbar"),
639 #endif
640         W("search/field"),
641         W("search/decoration"),
642         W("search/results_button"),
643         W("search/results_decoration"),
644         W("search/cancel_button"),
645         W("slider/vertical"),
646         W("slider/horizontal"),
647         W("slider/thumb_vertical"),
648         W("slider/thumb_horizontal"),
649 #if ENABLE(VIDEO)
650         W("mediacontrol/playpause_button"),
651         W("mediacontrol/mute_button"),
652         W("mediacontrol/seekforward_button"),
653         W("mediacontrol/seekbackward_button"),
654         W("mediacontrol/fullscreen_button"),
655 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
656         W("mediacontrol/slider_thumb"),
657 #endif
658 #endif
659         W("spinner"),
660 #undef W
661         0
662     };
663     ASSERT(type >= 0);
664     ASSERT((size_t)type < sizeof(groups) / sizeof(groups[0])); // out of sync?
665     return groups[type];
666 }
667
668 void RenderThemeEfl::applyPartDescriptions()
669 {
670     Evas_Object* object;
671     unsigned int i;
672     const char* file;
673
674     ASSERT(m_canvas);
675     ASSERT(m_edje);
676
677     edje_object_file_get(m_edje, &file, 0);
678     ASSERT(file);
679
680     object = edje_object_add(ecore_evas_get(m_canvas));
681     if (!object) {
682         EINA_LOG_ERR("Could not create Edje object.");
683         return;
684     }
685
686     for (i = 0; i < FormTypeLast; i++) {
687         FormType type = static_cast<FormType>(i);
688         const char* group = edjeGroupFromFormType(type);
689         m_partDescs[i].type = type;
690         if (!edje_object_file_set(object, file, group)) {
691             Edje_Load_Error err = edje_object_load_error_get(object);
692             const char* errmsg = edje_load_error_str(err);
693             EINA_LOG_ERR("Could not set theme group '%s' of file '%s': %s",
694                          group, file, errmsg);
695
696             applyPartDescriptionFallback(m_partDescs + i);
697         } else
698             applyPartDescription(object, m_partDescs + i);
699     }
700     evas_object_del(object);
701 }
702
703 void RenderThemeEfl::themeChanged()
704 {
705     cacheThemePartFlush();
706
707     if (!m_canvas) {
708         createCanvas();
709         if (!m_canvas)
710             return;
711     }
712
713     if (!m_edje) {
714         createEdje();
715         if (!m_edje)
716             return;
717     }
718
719     applyEdjeColors();
720     applyPartDescriptions();
721 }
722
723 RenderThemeEfl::RenderThemeEfl(Page* page)
724     : RenderTheme()
725     , m_page(page)
726     , m_activeSelectionBackgroundColor(0, 0, 255)
727     , m_activeSelectionForegroundColor(Color::white)
728     , m_inactiveSelectionBackgroundColor(0, 0, 128)
729     , m_inactiveSelectionForegroundColor(200, 200, 200)
730     , m_focusRingColor(32, 32, 224, 224)
731 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
732     , m_sliderThumbColor(0xee, 0xee, 0xee)
733 #else
734     , m_sliderThumbColor(Color::darkGray)
735 #endif
736 #if ENABLE(VIDEO)
737 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
738     , m_mediaPanelColor(0, 0, 0, 0)
739     , m_mediaSliderColor(0xDC, 0xDC, 0xDC, 0x80)
740     , m_mediaBufferingColor(0x96, 0x96, 0x96)
741     , m_mediaPlayingColor(0x36, 0x8A, 0xFF)
742 #else
743     , m_mediaPanelColor(220, 220, 195) // light tannish color.
744     , m_mediaSliderColor(Color::white)
745 #endif
746 #endif
747     , m_canvas(0)
748     , m_edje(0)
749     , m_supportsSelectionForegroundColors(false)
750 {
751 }
752
753 RenderThemeEfl::~RenderThemeEfl()
754 {
755     cacheThemePartFlush();
756
757     if (m_canvas) {
758         if (m_edje)
759             evas_object_del(m_edje);
760         ecore_evas_free(m_canvas);
761     }
762 }
763
764 void RenderThemeEfl::setSelectionForegroundColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA)
765 {
766     m_activeSelectionForegroundColor = Color(foreR, foreG, foreB, foreA);
767     m_inactiveSelectionForegroundColor = Color(backR, backG, backB, backA);
768     m_supportsSelectionForegroundColors = true;
769     platformColorsDidChange();
770 }
771
772 void RenderThemeEfl::setSelectionBackgroundColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA)
773 {
774     m_activeSelectionBackgroundColor = Color(foreR, foreG, foreB, foreA);
775     m_inactiveSelectionBackgroundColor = Color(backR, backG, backB, backA);
776     platformColorsDidChange();
777 }
778
779 void RenderThemeEfl::setFocusRingColor(int r, int g, int b, int a)
780 {
781     m_focusRingColor = Color(r, g, b, a);
782     // webkit just use platformFocusRingColor() for default theme (without page)
783     // this is ugly, but no other way to do it unless we change
784     // it to use page themes as much as possible.
785     RenderTheme::setCustomFocusRingColor(m_focusRingColor);
786     platformColorsDidChange();
787 }
788
789 static bool supportsFocus(ControlPart appearance)
790 {
791     switch (appearance) {
792     case PushButtonPart:
793     case ButtonPart:
794     case TextFieldPart:
795     case TextAreaPart:
796     case SearchFieldPart:
797     case MenulistPart:
798     case RadioPart:
799     case CheckboxPart:
800     case SliderVerticalPart:
801     case SliderHorizontalPart:
802         return true;
803     default:
804         return false;
805     }
806 }
807
808 bool RenderThemeEfl::supportsFocusRing(const RenderStyle* style) const
809 {
810     return supportsFocus(style->appearance());
811 }
812
813 bool RenderThemeEfl::controlSupportsTints(const RenderObject* object) const
814 {
815     return isEnabled(object);
816 }
817
818 LayoutUnit RenderThemeEfl::baselinePosition(const RenderObject* object) const
819 {
820     if (!object->isBox())
821         return 0;
822
823     if (object->style()->appearance() == CheckboxPart
824     ||  object->style()->appearance() == RadioPart)
825         return toRenderBox(object)->marginTop() + toRenderBox(object)->height() - 3;
826
827     return RenderTheme::baselinePosition(object);
828 }
829
830 bool RenderThemeEfl::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
831 {
832     if (object->style()->appearance() == SliderHorizontalPart)
833         return paintThemePart(object, SliderHorizontal, info, rect);
834     return paintThemePart(object, SliderVertical, info, rect);
835 }
836
837 void RenderThemeEfl::adjustSliderTrackStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
838 {
839     style->setBoxShadow(nullptr);
840 }
841
842 void RenderThemeEfl::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
843 {
844     RenderTheme::adjustSliderThumbStyle(styleResolver, style, element);
845     style->setBoxShadow(nullptr);
846 }
847
848 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
849 void RenderThemeEfl::adjustSliderThumbSize(RenderStyle* style, Element* element) const
850 #else
851 void RenderThemeEfl::adjustSliderThumbSize(RenderStyle* style, Element*) const
852 #endif
853 {
854     ControlPart part = style->appearance();
855     if (part == SliderThumbVerticalPart) {
856         style->setWidth(Length(sliderThumbHeight, Fixed));
857         style->setHeight(Length(sliderThumbWidth, Fixed));
858     } else if (part == SliderThumbHorizontalPart) {
859         style->setWidth(Length(sliderThumbWidth, Fixed));
860         style->setHeight(Length(sliderThumbHeight, Fixed));
861 #if ENABLE(VIDEO)
862     } else if (part == MediaSliderThumbPart) {
863 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
864        if(element && (element->document()->webkitIsFullScreen() ||element->document()->isMediaDocument())){
865             style->setWidth(Length(mediaSliderFullScreenThumbWidth, Fixed));
866             style->setHeight(Length(mediaSliderFullScreenThumbWidth, Fixed));
867             return;
868         }
869 #endif
870         style->setWidth(Length(mediaSliderThumbWidth, Fixed));
871         style->setHeight(Length(mediaSliderThumbHeight, Fixed));
872 #endif
873     }
874 }
875
876 #if ENABLE(DATALIST_ELEMENT)
877 IntSize RenderThemeEfl::sliderTickSize() const
878 {
879     // FIXME: We need to set this to the size of one tick mark.
880     return IntSize(0, 0);
881 }
882
883 int RenderThemeEfl::sliderTickOffsetFromTrackCenter() const
884 {
885     // FIXME: We need to set this to the position of the tick marks.
886     return 0;
887 }
888 #endif
889
890 bool RenderThemeEfl::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
891 {
892     if (object->style()->appearance() == SliderThumbHorizontalPart)
893         paintThemePart(object, SliderThumbHorizontal, info, rect);
894     else
895         paintThemePart(object, SliderThumbVertical, info, rect);
896
897     return false;
898 }
899
900 void RenderThemeEfl::adjustCheckboxStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
901 {
902     if (!m_page && element && element->document()->page()) {
903         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustCheckboxStyle(styleResolver, style, element);
904         return;
905     }
906     adjustSizeConstraints(style, CheckBox);
907     style->resetBorder();
908
909     const struct ThemePartDesc *desc = m_partDescs + (size_t)CheckBox;
910     if (style->width().value() < desc->min.width().value())
911         style->setWidth(desc->min.width());
912     if (style->height().value() < desc->min.height().value())
913         style->setHeight(desc->min.height());
914 }
915
916 bool RenderThemeEfl::paintCheckbox(RenderObject* object, const PaintInfo& info, const IntRect& rect)
917 {
918     return paintThemePart(object, CheckBox, info, rect);
919 }
920
921 void RenderThemeEfl::adjustRadioStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
922 {
923     if (!m_page && element && element->document()->page()) {
924         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustRadioStyle(styleResolver, style, element);
925         return;
926     }
927     adjustSizeConstraints(style, RadioButton);
928     style->resetBorder();
929
930     const struct ThemePartDesc *desc = m_partDescs + (size_t)RadioButton;
931     if (style->width().value() < desc->min.width().value())
932         style->setWidth(desc->min.width());
933     if (style->height().value() < desc->min.height().value())
934         style->setHeight(desc->min.height());
935 }
936
937 bool RenderThemeEfl::paintRadio(RenderObject* object, const PaintInfo& info, const IntRect& rect)
938 {
939     return paintThemePart(object, RadioButton, info, rect);
940 }
941
942 void RenderThemeEfl::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
943 {
944     if (!m_page && element && element->document()->page()) {
945         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustButtonStyle(styleResolver, style, element);
946         return;
947     }
948
949     // adjustSizeConstrains can make SquareButtonPart's size wrong (by adjusting paddings), so call it only for PushButtonPart and ButtonPart
950     if (style->appearance() == PushButtonPart || style->appearance() == ButtonPart)
951         adjustSizeConstraints(style, Button);
952 }
953
954 bool RenderThemeEfl::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
955 {
956     return paintThemePart(object, Button, info, rect);
957 }
958
959 void RenderThemeEfl::adjustMenuListStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
960 {
961     if (!m_page && element && element->document()->page()) {
962         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustMenuListStyle(styleResolver, style, element);
963         return;
964     }
965 #if ENABLE(TIZEN_THEME_STYLE_WORKAROUND)
966 /*If the computed height becomes greater than 12px, applying top padding causes the clipping of the text
967  This is just a workaround patch,this needs to be fixed with customized padding for different scenarios
968 like other ports win/safari do,as part of EFL Rendertheme refactoring. */
969
970     if(style->fontMetrics().height() >= RENDER_THEME_EFL_CONTROL_FONT_SIZE || style->appearance() == MenulistPart)
971       {    
972           const struct ThemePartDesc* desc = m_partDescs + (size_t)ComboBox;
973           style->setPaddingTop(Length(0,Fixed));
974           style->setPaddingLeft(style->paddingLeft());
975        //We need some amount of Right padding so that combo box arrow doesnt overlap the text
976        //if content doesnt set any right padding set EFL theme padding.
977        //Calculate the minimum right padding to avoid arrow overlapping with text.
978           int stylePaddingRight = style->paddingRight().intValue();
979           int themePaddingRight = desc->padding.right().intValue();
980           if(stylePaddingRight > themePaddingRight)
981               style->setPaddingRight(style->paddingRight());
982           else 
983               style->setPaddingRight(desc->padding.right());
984           style->setPaddingBottom(Length(1,Fixed));
985       } else
986 #endif
987
988     adjustSizeConstraints(style, ComboBox);
989     style->resetBorder();
990     style->setWhiteSpace(PRE);
991 }
992
993 bool RenderThemeEfl::paintMenuList(RenderObject* object, const PaintInfo& info, const IntRect& rect)
994 {
995     return paintThemePart(object, ComboBox, info, rect);
996 }
997
998 void RenderThemeEfl::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
999 {
1000     adjustMenuListStyle(styleResolver, style, element);
1001 }
1002
1003 bool RenderThemeEfl::paintMenuListButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1004 {
1005     return paintMenuList(object, info, rect);
1006 }
1007
1008 void RenderThemeEfl::adjustTextFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1009 {
1010 #if !ENABLE(TIZEN_THEME_STYLE_WORKAROUND)
1011     if (!m_page && element && element->document()->page()) {
1012         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustTextFieldStyle(styleResolver, style, element);
1013         return;
1014     }
1015     adjustSizeConstraints(style, TextField);
1016     style->resetBorder();
1017 #endif
1018 }
1019
1020 bool RenderThemeEfl::paintTextField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1021 {
1022     return paintThemePart(object, TextField, info, rect);
1023 }
1024
1025 void RenderThemeEfl::adjustTextAreaStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1026 {
1027     adjustTextFieldStyle(styleResolver, style, element);
1028 }
1029
1030 bool RenderThemeEfl::paintTextArea(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1031 {
1032     return paintTextField(object, info, rect);
1033 }
1034
1035 void RenderThemeEfl::adjustSearchFieldDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1036 {
1037     if (!m_page && element && element->document()->page()) {
1038         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldDecorationStyle(styleResolver, style, element);
1039         return;
1040     }
1041     adjustSizeConstraints(style, SearchFieldDecoration);
1042     style->resetBorder();
1043     style->setWhiteSpace(PRE);
1044 }
1045
1046 bool RenderThemeEfl::paintSearchFieldDecoration(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1047 {
1048     return paintThemePart(object, SearchFieldDecoration, info, rect);
1049 }
1050
1051 void RenderThemeEfl::adjustSearchFieldResultsButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1052 {
1053     if (!m_page && element && element->document()->page()) {
1054         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsButtonStyle(styleResolver, style, element);
1055         return;
1056     }
1057     adjustSizeConstraints(style, SearchFieldResultsButton);
1058     style->resetBorder();
1059     style->setWhiteSpace(PRE);
1060 }
1061
1062 bool RenderThemeEfl::paintSearchFieldResultsButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1063 {
1064     return paintThemePart(object, SearchFieldResultsButton, info, rect);
1065 }
1066
1067 void RenderThemeEfl::adjustSearchFieldResultsDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1068 {
1069     if (!m_page && element && element->document()->page()) {
1070         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldResultsDecorationStyle(styleResolver, style, element);
1071         return;
1072     }
1073     adjustSizeConstraints(style, SearchFieldResultsDecoration);
1074     style->resetBorder();
1075     style->setWhiteSpace(PRE);
1076 }
1077
1078 bool RenderThemeEfl::paintSearchFieldResultsDecoration(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1079 {
1080     return paintThemePart(object, SearchFieldResultsDecoration, info, rect);
1081 }
1082
1083 void RenderThemeEfl::adjustSearchFieldCancelButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1084 {
1085     if (!m_page && element && element->document()->page()) {
1086         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldCancelButtonStyle(styleResolver, style, element);
1087         return;
1088     }
1089     adjustSizeConstraints(style, SearchFieldCancelButton);
1090     style->resetBorder();
1091     style->setWhiteSpace(PRE);
1092
1093     // Logic taken from RenderThemeChromium.cpp.
1094     // Scale the button size based on the font size.
1095     float fontScale = style->fontSize() / defaultFontSize;
1096     int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultFontSize * fontScale), maxCancelButtonSize));
1097
1098     style->setWidth(Length(cancelButtonSize, Fixed));
1099     style->setHeight(Length(cancelButtonSize, Fixed));
1100 }
1101
1102 bool RenderThemeEfl::paintSearchFieldCancelButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1103 {
1104     return paintThemePart(object, SearchFieldCancelButton, info, rect);
1105 }
1106
1107 void RenderThemeEfl::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1108 {
1109     if (!m_page && element && element->document()->page()) {
1110         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustSearchFieldStyle(styleResolver, style, element);
1111         return;
1112     }
1113     adjustSizeConstraints(style, SearchField);
1114     style->resetBorder();
1115     style->setWhiteSpace(PRE);
1116 }
1117
1118 bool RenderThemeEfl::paintSearchField(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1119 {
1120     return paintThemePart(object, SearchField, info, rect);
1121 }
1122 #if !ENABLE(TIZEN_INPUTTYPE_NUMBER)
1123 void RenderThemeEfl::adjustInnerSpinButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
1124 {
1125     if (!m_page && element && element->document()->page()) {
1126         static_cast<RenderThemeEfl*>(element->document()->page()->theme())->adjustInnerSpinButtonStyle(styleResolver, style, element);
1127         return;
1128     }
1129     adjustSizeConstraints(style, Spinner);
1130 }
1131
1132 bool RenderThemeEfl::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1133 {
1134     return paintThemePart(object, Spinner, info, rect);
1135 }
1136 #endif
1137 void RenderThemeEfl::setDefaultFontSize(int size)
1138 {
1139     defaultFontSize = size;
1140 }
1141
1142 void RenderThemeEfl::systemFont(int propId, FontDescription& fontDescription) const
1143 {
1144     // It was called by RenderEmbeddedObject::paintReplaced to render alternative string.
1145     // To avoid cairo_error while rendering, fontDescription should be passed.
1146 #if ENABLE(TIZEN_SYSTEM_FONT)
1147     DEFINE_STATIC_LOCAL(String, fontFace, ("Arial"));
1148 #else
1149     DEFINE_STATIC_LOCAL(String, fontFace, ("Sans"));
1150 #endif
1151     float fontSize = defaultFontSize;
1152
1153     fontDescription.firstFamily().setFamily(fontFace);
1154     fontDescription.setSpecifiedSize(fontSize);
1155     fontDescription.setIsAbsoluteSize(true);
1156     fontDescription.setGenericFamily(FontDescription::NoFamily);
1157     fontDescription.setWeight(FontWeightNormal);
1158     fontDescription.setItalic(false);
1159 }
1160
1161 #if ENABLE(PROGRESS_ELEMENT)
1162 void RenderThemeEfl::adjustProgressBarStyle(StyleResolver*, RenderStyle* style, Element*) const
1163 {
1164     style->setBoxShadow(nullptr);
1165 }
1166
1167 double RenderThemeEfl::animationRepeatIntervalForProgressBar(RenderProgress*) const
1168 {
1169     return progressAnimationInterval;
1170 }
1171
1172 double RenderThemeEfl::animationDurationForProgressBar(RenderProgress*) const
1173 {
1174     return progressAnimationInterval * progressAnimationFrames * 2; // "2" for back and forth;
1175 }
1176
1177 bool RenderThemeEfl::paintProgressBar(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1178 {
1179     return paintThemePart(object, ProgressBar, info, rect);
1180 }
1181 #endif
1182
1183 #if ENABLE(VIDEO)
1184 bool RenderThemeEfl::emitMediaButtonSignal(FormType formType, MediaControlElementType mediaElementType, const IntRect& rect)
1185 {
1186     ThemePartCacheEntry* entry;
1187
1188     entry = cacheThemePartGet(formType, rect.size());
1189     ASSERT(entry);
1190     if (!entry)
1191         return false;
1192
1193     if (mediaElementType == MediaPlayButton)
1194         edje_object_signal_emit(entry->o, "play", "");
1195     else if (mediaElementType == MediaPauseButton)
1196         edje_object_signal_emit(entry->o, "pause", "");
1197     else if (mediaElementType == MediaMuteButton)
1198         edje_object_signal_emit(entry->o, "mute", "");
1199     else if (mediaElementType == MediaUnMuteButton)
1200         edje_object_signal_emit(entry->o, "sound", "");
1201     else if (mediaElementType == MediaSeekForwardButton)
1202         edje_object_signal_emit(entry->o, "seekforward", "");
1203     else if (mediaElementType == MediaSeekBackButton)
1204         edje_object_signal_emit(entry->o, "seekbackward", "");
1205     else if (mediaElementType == MediaEnterFullscreenButton)
1206         edje_object_signal_emit(entry->o, "fullscreen", "");
1207     else if (mediaElementType == MediaExitFullscreenButton)
1208         edje_object_signal_emit(entry->o, "normalscreen", "");
1209     else
1210         return false;
1211
1212     return true;
1213 }
1214
1215 String RenderThemeEfl::extraMediaControlsStyleSheet()
1216 {
1217 #if ENABLE(TIZEN_MEDIA_CONTROL_USER_AGENT_SHEET)
1218     return String(mediaControlsTizenUserAgentStyleSheet, sizeof(mediaControlsTizenUserAgentStyleSheet));
1219 #else
1220     return String(mediaControlsEflUserAgentStyleSheet, sizeof(mediaControlsEflUserAgentStyleSheet));
1221 #endif
1222 }
1223
1224 #if ENABLE(FULLSCREEN_API)
1225 #if ENABLE(TIZEN_MEDIA_CONTROL_USER_AGENT_SHEET)
1226 String RenderThemeEfl::extraFullScreenHorizontalStyleSheet()
1227 {
1228     return String(mediaControlsTizenFullscreenHorizontalUserAgentStyleSheet, sizeof(mediaControlsTizenFullscreenHorizontalUserAgentStyleSheet));
1229 }
1230
1231 String RenderThemeEfl::extraFullScreenVerticalStyleSheet()
1232 {
1233     return String(mediaControlsTizenFullscreenVerticalUserAgentStyleSheet, sizeof(mediaControlsTizenFullscreenVerticalUserAgentStyleSheet));
1234 }
1235 #else
1236 String RenderThemeEfl::extraFullScreenStyleSheet()
1237 {
1238     return String(mediaControlsEflFullscreenUserAgentStyleSheet, sizeof(mediaControlsEflFullscreenUserAgentStyleSheet));
1239 }
1240 #endif
1241 #endif
1242
1243 String RenderThemeEfl::formatMediaControlsCurrentTime(float currentTime, float duration) const
1244 {
1245 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1246     return formatMediaControlsTime(currentTime); // show current time only
1247 #else
1248     return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration);
1249 #endif
1250 }
1251
1252 bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1253 {
1254     Node* mediaNode = object->node() ? object->node()->shadowHost() : 0;
1255     if (!mediaNode)
1256         mediaNode = object->node();
1257     if (!mediaNode || (!mediaNode->hasTagName(videoTag)))
1258         return false;
1259
1260     if (!emitMediaButtonSignal(FullScreenButton, mediaControlElementType(object->node()), rect))
1261         return false;
1262
1263     return paintThemePart(object, FullScreenButton, info, rect);
1264 }
1265
1266 bool RenderThemeEfl::paintMediaMuteButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1267 {
1268     Node* mediaNode = object->node() ? object->node()->shadowHost() : 0;
1269     if (!mediaNode)
1270         mediaNode = object->node();
1271     if (!mediaNode || !mediaNode->isElementNode() || !static_cast<Element*>(mediaNode)->isMediaElement())
1272         return false;
1273
1274     HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode);
1275
1276     if (!emitMediaButtonSignal(MuteUnMuteButton, mediaElement->muted() ? MediaMuteButton : MediaUnMuteButton, rect))
1277         return false;
1278
1279     return paintThemePart(object, MuteUnMuteButton, info, rect);
1280 }
1281
1282 bool RenderThemeEfl::paintMediaPlayButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1283 {
1284     Node* node = object->node();
1285     if (!node || !node->isMediaControlElement())
1286         return false;
1287
1288     if (!emitMediaButtonSignal(PlayPauseButton, mediaControlElementType(node), rect))
1289         return false;
1290
1291     return paintThemePart(object, PlayPauseButton, info, rect);
1292 }
1293
1294 bool RenderThemeEfl::paintMediaSeekBackButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1295 {
1296     Node* node = object->node();
1297     if (!node || !node->isMediaControlElement())
1298         return 0;
1299
1300     if (!emitMediaButtonSignal(SeekBackwardButton, mediaControlElementType(node), rect))
1301         return false;
1302
1303     return paintThemePart(object, SeekBackwardButton, info, rect);
1304 }
1305
1306 bool RenderThemeEfl::paintMediaSeekForwardButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1307 {
1308     Node* node = object->node();
1309     if (!node || !node->isMediaControlElement())
1310         return 0;
1311
1312     if (!emitMediaButtonSignal(SeekForwardButton, mediaControlElementType(node), rect))
1313         return false;
1314
1315     return paintThemePart(object, SeekForwardButton, info, rect);
1316 }
1317
1318 bool RenderThemeEfl::paintMediaSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1319 {
1320     GraphicsContext* context = info.context;
1321
1322 #if !ENABLE(TIZEN_GSTREAMER_VIDEO)
1323     context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1324     context->fillRect(FloatRect(IntRect(rect.x(), rect.y() + (rect.height() - mediaSliderHeight) / 2,
1325                                         rect.width(), mediaSliderHeight)), m_mediaSliderColor, ColorSpaceDeviceRGB);
1326 #endif
1327
1328     RenderStyle* style = object->style();
1329     HTMLMediaElement* mediaElement = toParentMediaElement(object);
1330
1331     if (!mediaElement)
1332         return false;
1333
1334 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1335     int thumbWidth;
1336     if (mediaElement->isFullscreen() || mediaElement->ownerDocument()->isMediaDocument())
1337         thumbWidth = mediaSliderFullScreenThumbWidth;
1338     else
1339         thumbWidth = mediaSliderThumbWidth;
1340
1341     context->setLineCap(RoundCap);
1342     context->setStrokeStyle(SolidStroke);
1343     context->setStrokeColor(m_mediaSliderColor, ColorSpaceDeviceRGB);
1344     context->setStrokeThickness(rect.height());
1345     context->drawLine(IntPoint(rect.x() + thumbWidth / 2 , rect.y() + rect.height() / 2), IntPoint(rect.x() + rect.width() - thumbWidth / 2, rect.y() + rect.height() / 2));
1346 #endif // ENABLE(TIZEN_GSTREAMER_VIDEO)
1347
1348     // Draw the buffered ranges. This code is highly inspired from
1349     // Chrome for the gradient code.
1350     float mediaDuration = mediaElement->duration();
1351     RefPtr<TimeRanges> timeRanges = mediaElement->buffered();
1352     IntRect trackRect = rect;
1353     int totalWidth = trackRect.width();
1354
1355     trackRect.inflate(-style->borderLeftWidth());
1356 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1357     trackRect.setX(rect.x() + thumbWidth/2);
1358     totalWidth = trackRect.width() - thumbWidth;
1359     trackRect.setY(rect.y() + rect.height() / 2);
1360 #endif
1361     context->save();
1362     context->setStrokeStyle(NoStroke);
1363
1364 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1365     float suspendedPoint = 0;
1366 #endif
1367     for (unsigned index = 0; index < timeRanges->length(); ++index) {
1368         ExceptionCode ignoredException;
1369         float start = timeRanges->start(index, ignoredException);
1370         float end = timeRanges->end(index, ignoredException);
1371         int width = ((end - start) * totalWidth) / mediaDuration;
1372         IntRect rangeRect;
1373         if (!index) {
1374             rangeRect = trackRect;
1375             rangeRect.setWidth(width);
1376         } else {
1377 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1378             if (suspendedPoint != start) {
1379                 start = suspendedPoint;
1380                 width = ((end - start) * totalWidth) / mediaDuration;
1381             }
1382 #endif
1383             rangeRect.setLocation(IntPoint(trackRect.x() + start / mediaDuration* totalWidth, trackRect.y()));
1384             rangeRect.setSize(IntSize(width, trackRect.height()));
1385         }
1386 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1387         suspendedPoint = timeRanges->end(index, ignoredException);
1388 #endif
1389
1390         // Don't bother drawing empty range.
1391         if (rangeRect.isEmpty())
1392             continue;
1393
1394         IntPoint sliderTopLeft = rangeRect.location();
1395         IntPoint sliderTopRight = sliderTopLeft;
1396         sliderTopRight.move(0, rangeRect.height());
1397
1398 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1399         // In case of some files, metadata is positioned at end of file.
1400         // Don't show this.
1401         if (timeRanges->length() > 1 && index == timeRanges->length() - 1)
1402             break;
1403
1404         context->setLineCap(RoundCap);
1405         context->setStrokeStyle(SolidStroke);
1406         context->setStrokeColor(m_mediaBufferingColor, ColorSpaceDeviceRGB);
1407         context->setStrokeThickness(rangeRect.height());
1408         context->drawLine(IntPoint(rangeRect.x(), rangeRect.y()), IntPoint(rangeRect.x() + rangeRect.width(), rangeRect.y()));
1409 #else
1410         context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1411 #endif
1412     }
1413
1414 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1415     float currentTime = mediaElement->currentTime();
1416     if (currentTime > mediaDuration)
1417         currentTime = mediaDuration;
1418
1419     int width = (currentTime * totalWidth) / mediaDuration;
1420     if (width > 0)
1421     {
1422         context->setLineCap(RoundCap);
1423         context->setStrokeStyle(SolidStroke);
1424         context->setStrokeColor(m_mediaPlayingColor, ColorSpaceDeviceRGB);
1425         context->setStrokeThickness(trackRect.height());
1426         context->drawLine(IntPoint(trackRect.x(), trackRect.y()), IntPoint(trackRect.x() + width, trackRect.y()));
1427     }
1428 #endif
1429
1430     context->restore();
1431     return true;
1432 }
1433
1434 bool RenderThemeEfl::paintMediaSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1435 {
1436 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1437     if (object->style()->appearance() == MediaSliderThumbPart)
1438         return paintThemePart(object, SliderThumb, info, rect);
1439     else
1440         return false;
1441 #else
1442     IntSize thumbRect(3, 3);
1443     info.context->fillRoundedRect(rect, thumbRect, thumbRect, thumbRect, thumbRect, m_sliderThumbColor, ColorSpaceDeviceRGB);
1444     return true;
1445 #endif
1446 }
1447
1448 bool RenderThemeEfl::paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo& info, const IntRect& rect)
1449 {
1450     notImplemented();
1451     return false;
1452 }
1453
1454 bool RenderThemeEfl::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1455 {
1456     notImplemented();
1457     return false;
1458 }
1459
1460 bool RenderThemeEfl::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1461 {
1462     notImplemented();
1463     return false;
1464 }
1465
1466 bool RenderThemeEfl::paintMediaCurrentTime(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1467 {
1468     info.context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1469     return true;
1470 }
1471
1472 #if ENABLE(TIZEN_GSTREAMER_VIDEO)
1473 bool RenderThemeEfl::paintMediaTimeRemaining(RenderObject* object, const PaintInfo& info, const IntRect& rect)
1474 {
1475     info.context->fillRect(FloatRect(rect), m_mediaPanelColor, ColorSpaceDeviceRGB);
1476     return true;
1477 }
1478 #endif
1479
1480 #endif
1481 }