Changeset 128274 in webkit


Ignore:
Timestamp:
Sep 12, 2012 12:55:48 AM (12 years ago)
Author:
kenneth@webkit.org
Message:

[EFL] Clean up the RenderTheme Edje caching
https://bugs.webkit.org/show_bug.cgi?id=96016

Reviewed by Gyuyoung Kim.

Refactor the Edje parts caching to be easier to understand and use
proper C++ constructs.

  • platform/efl/RenderThemeEfl.cpp:

(WebCore):
(WebCore::toEdjeGroup):

Converts the enum to the given edje group name.

(WebCore::setSourceGroupForEdjeObject):

Basically a wrapper around evas_object_file_set, but handles
errors, which was done slightly differently all over.

(WebCore::RenderThemeEfl::ThemePartCacheEntry::ThemePartCacheEntry):
(WebCore::RenderThemeEfl::ThemePartCacheEntry::~ThemePartCacheEntry):

(WebCore::createCairoSurfaceFor):
(WebCore::isFormElementTooLargeToDisplay):

Methods used when creating ThemePartCacheEntry'es.

(WebCore::RenderThemeEfl::ThemePartCacheEntry::create):
(WebCore::RenderThemeEfl::ThemePartCacheEntry::reuse):

New methods for creating and reusing an cache entry. If you do
not supply a new size, the original size will be used, and it is
thus more effective.

(WebCore::RenderThemeEfl::getThemePartFromCache):

New method for requesting a theme part. If it doesn't exist
it will additinally be loaded and added to the cache.

(WebCore::RenderThemeEfl::flushThemePartCache):

Remove the entire cache and free the assets.

(WebCore::RenderThemeEfl::paintThemePart):
(WebCore::RenderThemeEfl::themePath):
(WebCore::RenderThemeEfl::loadTheme):
(WebCore::RenderThemeEfl::applyPartDescriptionsFrom):
(WebCore::RenderThemeEfl::~RenderThemeEfl):
(WebCore::RenderThemeEfl::emitMediaButtonSignal):

  • platform/efl/RenderThemeEfl.h:

(RenderThemeEfl):
(ThemePartCacheEntry):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r128269 r128274  
     12012-09-12  Kenneth Rohde Christiansen  <kenneth@webkit.org>
     2
     3        [EFL] Clean up the RenderTheme Edje caching
     4        https://bugs.webkit.org/show_bug.cgi?id=96016
     5
     6        Reviewed by Gyuyoung Kim.
     7
     8        Refactor the Edje parts caching to be easier to understand and use
     9        proper C++ constructs.
     10
     11        * platform/efl/RenderThemeEfl.cpp:
     12        (WebCore):
     13        (WebCore::toEdjeGroup):
     14
     15            Converts the enum to the given edje group name.
     16
     17        (WebCore::setSourceGroupForEdjeObject):
     18
     19            Basically a wrapper around evas_object_file_set, but handles
     20            errors, which was done slightly differently all over.
     21
     22        (WebCore::RenderThemeEfl::ThemePartCacheEntry::ThemePartCacheEntry):
     23        (WebCore::RenderThemeEfl::ThemePartCacheEntry::~ThemePartCacheEntry):
     24
     25        (WebCore::createCairoSurfaceFor):
     26        (WebCore::isFormElementTooLargeToDisplay):
     27
     28            Methods used when creating ThemePartCacheEntry'es.
     29
     30        (WebCore::RenderThemeEfl::ThemePartCacheEntry::create):
     31        (WebCore::RenderThemeEfl::ThemePartCacheEntry::reuse):
     32
     33            New methods for creating and reusing an cache entry. If you do
     34            not supply a new size, the original size will be used, and it is
     35            thus more effective.
     36
     37        (WebCore::RenderThemeEfl::getThemePartFromCache):
     38
     39            New method for requesting a theme part. If it doesn't exist
     40            it will additinally be loaded and added to the cache.
     41
     42        (WebCore::RenderThemeEfl::flushThemePartCache):
     43
     44            Remove the entire cache and free the assets.
     45
     46        (WebCore::RenderThemeEfl::paintThemePart):
     47        (WebCore::RenderThemeEfl::themePath):
     48        (WebCore::RenderThemeEfl::loadTheme):
     49        (WebCore::RenderThemeEfl::applyPartDescriptionsFrom):
     50        (WebCore::RenderThemeEfl::~RenderThemeEfl):
     51        (WebCore::RenderThemeEfl::emitMediaButtonSignal):
     52        * platform/efl/RenderThemeEfl.h:
     53        (RenderThemeEfl):
     54        (ThemePartCacheEntry):
     55
    1562012-09-12  Alexandre Elias  <aelias@chromium.org>
    257
  • trunk/Source/WebCore/platform/efl/RenderThemeEfl.cpp

    r128149 r128274  
    8585    do { if (!o) { EINA_LOG_CRIT(fmt, ## __VA_ARGS__); ASSERT(o); return val; } } while (0)
    8686
    87 void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) const
    88 {
    89     loadThemeIfNeeded();
    90     _ASSERT_ON_RELEASE_RETURN(m_edje, "Could not paint native HTML part due to missing theme.");
    91 
    92     const struct ThemePartDesc* desc = m_partDescs + (size_t)type;
    93 
    94     if (style->minWidth().isIntrinsic())
    95         style->setMinWidth(desc->min.width());
    96     if (style->minHeight().isIntrinsic())
    97         style->setMinHeight(desc->min.height());
    98 
    99     if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto())
    100         style->setMaxWidth(desc->max.width());
    101     if (desc->max.height().value() > 0 && style->maxHeight().isIntrinsicOrAuto())
    102         style->setMaxHeight(desc->max.height());
    103 
    104     style->setPaddingTop(desc->padding.top());
    105     style->setPaddingBottom(desc->padding.bottom());
    106     style->setPaddingLeft(desc->padding.left());
    107     style->setPaddingRight(desc->padding.right());
    108 }
    109 
    110 bool RenderThemeEfl::themePartCacheEntryReset(struct ThemePartCacheEntry* entry, FormType type)
    111 {
    112     const char *file, *group;
    113 
    114     ASSERT(entry);
    115     ASSERT(m_edje);
    116 
    117     edje_object_file_get(m_edje, &file, 0);
    118     group = edjeGroupFromFormType(type);
    119     ASSERT(file);
    120     ASSERT(group);
    121 
    122     if (!edje_object_file_set(entry->o, file, group)) {
    123         Edje_Load_Error err = edje_object_load_error_get(entry->o);
    124         const char *errmsg = edje_load_error_str(err);
    125         EINA_LOG_ERR("Could not load '%s' from theme %s: %s", group, file, errmsg);
    126         return false;
    127     }
    128     return true;
    129 }
    130 
    131 bool RenderThemeEfl::themePartCacheEntrySurfaceCreate(struct ThemePartCacheEntry* entry)
    132 {
    133     int w, h;
    134     cairo_status_t status;
    135 
    136     ASSERT(entry);
    137     ASSERT(entry->ee);
    138 
    139     ecore_evas_geometry_get(entry->ee, 0, 0, &w, &h);
    140     ASSERT(w > 0);
    141     ASSERT(h > 0);
    142 
    143     entry->surface = cairo_image_surface_create_for_data((unsigned char *)ecore_evas_buffer_pixels_get(entry->ee),
    144                                                       CAIRO_FORMAT_ARGB32, w, h, w * 4);
    145     status = cairo_surface_status(entry->surface);
    146     if (status != CAIRO_STATUS_SUCCESS) {
    147         EINA_LOG_ERR("Could not create cairo surface: %s",
    148                      cairo_status_to_string(status));
    149         return false;
    150     }
    151 
    152     return true;
    153 }
    154 
    155 bool RenderThemeEfl::isFormElementTooLargeToDisplay(const IntSize& elementSize)
    156 {
    157     // This limit of 20000 pixels is hardcoded inside edje -- anything above this size
    158     // will be clipped. This value seems to be reasonable enough so that hardcoding it
    159     // here won't be a problem.
    160     static const int maxEdjeDimension = 20000;
    161 
    162     return elementSize.width() > maxEdjeDimension || elementSize.height() > maxEdjeDimension;
    163 }
    164 
    165 // allocate a new entry and fill it with edje group
    166 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartNew(FormType type, const IntSize& size)
    167 {
    168     if (isFormElementTooLargeToDisplay(size)) {
    169         EINA_LOG_ERR("Cannot render an element of size %dx%d.", size.width(), size.height());
    170         return 0;
    171     }
    172 
    173     ThemePartCacheEntry* entry = new ThemePartCacheEntry;
    174     if (!entry) {
    175         EINA_LOG_ERR("could not allocate ThemePartCacheEntry.");
    176         return 0;
    177     }
    178 
    179     entry->ee = ecore_evas_buffer_new(size.width(), size.height());
    180     if (!entry->ee) {
    181         EINA_LOG_ERR("ecore_evas_buffer_new(%d, %d) failed.",
    182                      size.width(), size.height());
    183         delete entry;
    184         return 0;
    185     }
    186 
    187     // By default EFL creates buffers without alpha.
    188     ecore_evas_alpha_set(entry->ee, EINA_TRUE);
    189 
    190     entry->o = edje_object_add(ecore_evas_get(entry->ee));
    191     ASSERT(entry->o);
    192     if (!themePartCacheEntryReset(entry, type)) {
    193         evas_object_del(entry->o);
    194         ecore_evas_free(entry->ee);
    195         delete entry;
    196         return 0;
    197     }
    198 
    199     if (!themePartCacheEntrySurfaceCreate(entry)) {
    200         evas_object_del(entry->o);
    201         ecore_evas_free(entry->ee);
    202         delete entry;
    203         return 0;
    204     }
    205 
    206     evas_object_resize(entry->o, size.width(), size.height());
    207     evas_object_show(entry->o);
    208 
    209     entry->type = type;
    210     entry->size = size;
    211 
    212     m_partCache.prepend(entry);
    213     return entry;
    214 }
    215 
    216 // just change the edje group and return the same entry
    217 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartReset(FormType type, struct RenderThemeEfl::ThemePartCacheEntry* entry)
    218 {
    219     if (!themePartCacheEntryReset(entry, type)) {
    220         entry->type = FormTypeLast; // invalidate
    221         m_partCache.append(entry);
    222         return 0;
    223     }
    224     entry->type = type;
    225     m_partCache.prepend(entry);
    226     return entry;
    227 }
    228 
    229 // resize entry and reset it
    230 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartResizeAndReset(FormType type, const IntSize& size, struct RenderThemeEfl::ThemePartCacheEntry* entry)
    231 {
    232     cairo_surface_finish(entry->surface);
    233 
    234     entry->size = size;
    235     ecore_evas_resize(entry->ee, size.width(), size.height());
    236     evas_object_resize(entry->o, size.width(), size.height());
    237 
    238     if (!themePartCacheEntrySurfaceCreate(entry)) {
    239         evas_object_del(entry->o);
    240         ecore_evas_free(entry->ee);
    241         delete entry;
    242         return 0;
    243     }
    244 
    245     return cacheThemePartReset(type, entry);
    246 }
    247 
    248 // general purpose get (will create, reuse and all)
    249 struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartGet(FormType type, const IntSize& size)
    250 {
    251     Vector<struct ThemePartCacheEntry *>::iterator itr, end;
    252     struct ThemePartCacheEntry *ce_last_size = 0;
    253     int i, idxLastSize = -1;
    254 
    255     itr = m_partCache.begin();
    256     end = m_partCache.end();
    257     for (i = 0; itr != end; i++, itr++) {
    258         struct ThemePartCacheEntry *entry = *itr;
    259         if (entry->size == size) {
    260             if (entry->type == type)
    261                 return entry;
    262             ce_last_size = entry;
    263             idxLastSize = i;
    264         }
    265     }
    266 
    267     if (m_partCache.size() < RENDER_THEME_EFL_PART_CACHE_MAX)
    268         return cacheThemePartNew(type, size);
    269 
    270     if (ce_last_size && ce_last_size != m_partCache.first()) {
    271         m_partCache.remove(idxLastSize);
    272         return cacheThemePartReset(type, ce_last_size);
    273     }
    274 
    275     ThemePartCacheEntry* entry = m_partCache.last();
    276     m_partCache.removeLast();
    277     return cacheThemePartResizeAndReset(type, size, entry);
    278 }
    279 
    280 void RenderThemeEfl::cacheThemePartFlush()
    281 {
    282     Vector<struct ThemePartCacheEntry *>::iterator itr, end;
    283 
    284     itr = m_partCache.begin();
    285     end = m_partCache.end();
    286     for (; itr != end; itr++) {
    287         struct ThemePartCacheEntry *entry = *itr;
    288         cairo_surface_destroy(entry->surface);
    289         evas_object_del(entry->o);
    290         ecore_evas_free(entry->ee);
    291         delete entry;
    292     }
    293     m_partCache.clear();
    294 }
    295 
    296 void RenderThemeEfl::applyEdjeStateFromForm(Evas_Object* object, ControlStates states)
    297 {
    298     const char *signals[] = { // keep in sync with WebCore/platform/ThemeTypes.h
    299         "hovered",
    300         "pressed",
    301         "focused",
    302         "enabled",
    303         "checked",
    304         "read-only",
    305         "default",
    306         "window-inactive",
    307         "indeterminate",
    308         "spinup"
    309     };
    310 
    311     edje_object_signal_emit(object, "reset", "");
    312 
    313     for (size_t i = 0; i < WTF_ARRAY_LENGTH(signals); ++i) {
    314         if (states & (1 << i))
    315             edje_object_signal_emit(object, signals[i], "");
    316     }
    317 }
    318 
    319 bool RenderThemeEfl::paintThemePart(RenderObject* object, FormType type, const PaintInfo& info, const IntRect& rect)
    320 {
    321     loadThemeIfNeeded();
    322     _ASSERT_ON_RELEASE_RETURN_VAL(m_edje, false, "Could not paint native HTML part due to missing theme.");
    323 
    324     ThemePartCacheEntry* entry;
    325     Eina_List* updates;
    326     cairo_t* cairo;
    327 
    328     entry = cacheThemePartGet(type, rect.size());
    329     if (!entry)
    330         return false;
    331 
    332     applyEdjeStateFromForm(entry->o, controlStatesForRenderer(object));
    333 
    334     cairo = info.context->platformContext()->cr();
    335     ASSERT(cairo);
    336 
    337     // Currently, only sliders needs this message; if other widget ever needs special
    338     // treatment, move them to special functions.
    339     if (type == SliderVertical || type == SliderHorizontal) {
    340         if (!object->isSlider())
    341             return true; // probably have -webkit-appearance: slider..
    342 
    343         RenderSlider* renderSlider = toRenderSlider(object);
    344         HTMLInputElement* input = renderSlider->node()->toInputElement();
    345         double valueRange = input->maximum() - input->minimum();
    346 
    347         OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
    348         Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
    349         msg->count = 2;
    350 
    351         // The first parameter of the message decides if the progress bar
    352         // grows from the end of the slider or from the beginning. On vertical
    353         // sliders, it should always be the same and will not be affected by
    354         // text direction settings.
    355         if (object->style()->direction() == RTL || type == SliderVertical)
    356             msg->val[0] = 1;
    357         else
    358             msg->val[0] = 0;
    359 
    360         msg->val[1] = (input->valueAsNumber() - input->minimum()) / valueRange;
    361         edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
    362 #if ENABLE(PROGRESS_ELEMENT)
    363     } else if (type == ProgressBar) {
    364         RenderProgress* renderProgress = toRenderProgress(object);
    365 
    366         int max = rect.width();
    367         double value = renderProgress->position();
    368 
    369         OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
    370         Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
    371         msg->count = 2;
    372 
    373         if (object->style()->direction() == RTL)
    374             msg->val[0] = (1.0 - value) * max;
    375         else
    376             msg->val[0] = 0;
    377         msg->val[1] = value;
    378         edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
    379 #endif
    380     }
    381 
    382     edje_object_calc_force(entry->o);
    383     edje_object_message_signal_process(entry->o);
    384     updates = evas_render_updates(ecore_evas_get(entry->ee));
    385     evas_render_updates_free(updates);
    386 
    387     cairo_save(cairo);
    388     cairo_set_source_surface(cairo, entry->surface, rect.x(), rect.y());
    389     cairo_paint_with_alpha(cairo, 1.0);
    390     cairo_restore(cairo);
    391 
    392     return false;
    393 }
    394 
    395 PassRefPtr<RenderTheme> RenderThemeEfl::create(Page* page)
    396 {
    397     return adoptRef(new RenderThemeEfl(page));
    398 }
    399 
    400 PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
    401 {
    402     if (page)
    403         return RenderThemeEfl::create(page);
    404 
    405     static RenderTheme* fallback = RenderThemeEfl::create(0).leakRef();
    406     return fallback;
    407 }
    408 
    409 static void applyColorCallback(void* data, Evas_Object*, const char* /* signal */, const char* colorClass)
    410 {
    411     RenderThemeEfl* that = static_cast<RenderThemeEfl*>(data);
    412     that->setColorFromThemeClass(colorClass);
    413     that->platformColorsDidChange(); // Triggers relayout.
    414 }
    415 
    416 static void fillColorsFromEdjeClass(Evas_Object* o, const char* colorClass, Color* color1, Color* color2 = 0, Color* color3 = 0)
    417 {
    418     int r1, g1, b1, a1;
    419     int r2, g2, b2, a2;
    420     int r3, g3, b3, a3;
    421 
    422     bool ok = edje_object_color_class_get(o, colorClass, &r1, &g1, &b1, &a1, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
    423     _ASSERT_ON_RELEASE_RETURN(ok, "Could not get color class '%s'\n", colorClass);
    424 
    425     if (color1)
    426         color1->setRGB(makeRGBA(r1, g1, b1, a1));
    427     if (color2)
    428         color2->setRGB(makeRGBA(r2, g2, b2, a2));
    429     if (color3)
    430         color3->setRGB(makeRGBA(r3, g3, b3, a3));
    431 }
    432 
    433 void RenderThemeEfl::setColorFromThemeClass(const char* colorClass)
    434 {
    435     ASSERT(m_edje);
    436 
    437     if (!strcmp("webkit/selection/active", colorClass))
    438         fillColorsFromEdjeClass(m_edje, colorClass, &m_activeSelectionForegroundColor, &m_activeSelectionBackgroundColor);
    439     else if (!strcmp("webkit/selection/inactive", colorClass))
    440         fillColorsFromEdjeClass(m_edje, colorClass, &m_inactiveSelectionForegroundColor, &m_inactiveSelectionBackgroundColor);
    441     else if (!strcmp("webkit/focus_ring", colorClass)) {
    442         fillColorsFromEdjeClass(m_edje, colorClass, &m_focusRingColor);
    443         // platformFocusRingColor() is only used for the default theme (without page)
    444         // The following is ugly, but no other way to do it unless we change it to use page themes as much as possible.
    445         RenderTheme::setCustomFocusRingColor(m_focusRingColor);
    446     }
    447 }
    448 
    449 void RenderThemeEfl::setThemePath(const String& path)
    450 {
    451     if (path == m_themePath)
    452         return;
    453 
    454     m_themePath = path;
    455 
    456     if (m_themePath.isEmpty()) {
    457         EINA_LOG_ERR("No theme defined, unable to set theme for HTML Forms.");
    458         return;
    459     }
    460 
    461     if (!m_canvas) {
    462         m_canvas = ecore_evas_buffer_new(1, 1);
    463         if (!m_canvas)
    464             EINA_LOG_ERR("Could not create canvas.");
    465     }
    466 
    467     loadTheme();
    468 }
    469 
    470 bool RenderThemeEfl::loadTheme()
    471 {
    472     Evas_Object* o = edje_object_add(ecore_evas_get(m_canvas));
    473     _ASSERT_ON_RELEASE_RETURN_VAL(o, false, "Could not create new base Edje object.");
    474 
    475     if (!edje_object_file_set(o, m_themePath.utf8().data(), "webkit/base")) {
    476         Edje_Load_Error err = edje_object_load_error_get(o);
    477         const char* errmsg = edje_load_error_str(err);
    478         EINA_LOG_ERR("Could not set file '%s': %s", m_themePath.utf8().data(),  errmsg);
    479         evas_object_del(o);
    480         return false; // Keep current theme.
    481     }
    482 
    483     // Get rid of existing theme.
    484     if (m_edje) {
    485         cacheThemePartFlush();
    486         evas_object_del(m_edje);
    487     }
    488 
    489     // Set new loaded theme, and apply it.
    490     m_edje = o;
    491 
    492     edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/selection/active", applyColorCallback, this);
    493     edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/selection/inactive", applyColorCallback, this);
    494     edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/focus_ring", applyColorCallback, this);
    495 
    496     applyPartDescriptionsFrom(m_edje);
    497 
    498     setColorFromThemeClass("webkit/selection/active");
    499     setColorFromThemeClass("webkit/selection/inactive");
    500     setColorFromThemeClass("webkit/focus_ring");
    501 
    502     platformColorsDidChange(); // Schedules a relayout, do last.
    503 
    504     return true;
    505 }
    506 
    507 void RenderThemeEfl::applyPartDescriptionFallback(struct ThemePartDesc* desc)
    508 {
    509     desc->min.setWidth(Length(0, Fixed));
    510     desc->min.setHeight(Length(0, Fixed));
    511 
    512     desc->max.setWidth(Length(0, Fixed));
    513     desc->max.setHeight(Length(0, Fixed));
    514 
    515     desc->padding = LengthBox(0, 0, 0, 0);
    516 }
    517 
    518 void RenderThemeEfl::applyPartDescription(Evas_Object* object, struct ThemePartDesc* desc)
    519 {
    520     Evas_Coord minw, minh, maxw, maxh;
    521 
    522     edje_object_size_min_get(object, &minw, &minh);
    523     if (!minw && !minh)
    524         edje_object_size_min_calc(object, &minw, &minh);
    525 
    526     desc->min.setWidth(Length(minw, Fixed));
    527     desc->min.setHeight(Length(minh, Fixed));
    528 
    529     edje_object_size_max_get(object, &maxw, &maxh);
    530     desc->max.setWidth(Length(maxw, Fixed));
    531     desc->max.setHeight(Length(maxh, Fixed));
    532 
    533     if (!edje_object_part_exists(object, "text_confinement"))
    534         desc->padding = LengthBox(0, 0, 0, 0);
    535     else {
    536         Evas_Coord px, py, pw, ph;
    537         Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
    538         int t, r, b, l;
    539 
    540         if (minw > 0)
    541             ow = minw;
    542         else
    543             ow = 100;
    544         if (minh > 0)
    545             oh = minh;
    546         else
    547             oh = 100;
    548         if (maxw > 0 && ow > maxw)
    549             ow = maxw;
    550         if (maxh > 0 && oh > maxh)
    551             oh = maxh;
    552 
    553         evas_object_move(object, ox, oy);
    554         evas_object_resize(object, ow, oh);
    555         edje_object_calc_force(object);
    556         edje_object_message_signal_process(object);
    557         edje_object_part_geometry_get(object, "text_confinement", &px, &py, &pw, &ph);
    558 
    559         t = py - oy;
    560         b = (oh + oy) - (ph + py);
    561 
    562         l = px - ox;
    563         r = (ow + ox) - (pw + px);
    564 
    565         desc->padding = LengthBox(t, r, b, l);
    566     }
    567 }
    568 
    569 const char* RenderThemeEfl::edjeGroupFromFormType(FormType type) const
     87
     88static const char* toEdjeGroup(FormType type)
    57089{
    57190    static const char* groups[] = {
     
    603122    };
    604123    ASSERT(type >= 0);
    605     ASSERT((size_t)type < sizeof(groups) / sizeof(groups[0])); // out of sync?
     124    ASSERT((size_t)type < sizeof(groups) / sizeof(groups[0])); // Out of sync?
    606125    return groups[type];
    607126}
    608127
    609 void RenderThemeEfl::applyPartDescriptionsFrom(Evas_Object* o)
    610 {
    611     Evas_Object* object;
    612     unsigned int i;
    613     const char* file;
    614 
     128static bool setSourceGroupForEdjeObject(Evas_Object* o, const String& themePath, const char* group)
     129{
    615130    ASSERT(o);
    616 
    617     edje_object_file_get(o, &file, 0);
    618     ASSERT(file);
    619     if (!file) {
    620         EINA_LOG_ERR("Could not retrieve Edje theme file.");
    621         return;
    622     }
    623 
    624     object = edje_object_add(ecore_evas_get(m_canvas));
    625     if (!object) {
    626         EINA_LOG_ERR("Could not create Edje object.");
    627         return;
    628     }
    629 
    630     for (i = 0; i < FormTypeLast; i++) {
     131    ASSERT(!themePath.isEmpty());
     132
     133    if (!edje_object_file_set(o, themePath.utf8().data(), group)) {
     134        const char* message = edje_load_error_str(edje_object_load_error_get(o));
     135        EINA_LOG_ERR("Could not set theme group '%s' of file '%s': %s", group, themePath.utf8().data(), message);
     136        return false;
     137    }
     138
     139    return true;
     140}
     141
     142void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) const
     143{
     144    loadThemeIfNeeded();
     145
     146    // These are always valid, even if no theme could be loaded.
     147    const ThemePartDesc* desc = m_partDescs + (size_t)type;
     148
     149    if (style->minWidth().isIntrinsic())
     150        style->setMinWidth(desc->min.width());
     151    if (style->minHeight().isIntrinsic())
     152        style->setMinHeight(desc->min.height());
     153
     154    if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto())
     155        style->setMaxWidth(desc->max.width());
     156    if (desc->max.height().value() > 0 && style->maxHeight().isIntrinsicOrAuto())
     157        style->setMaxHeight(desc->max.height());
     158
     159    style->setPaddingTop(desc->padding.top());
     160    style->setPaddingBottom(desc->padding.bottom());
     161    style->setPaddingLeft(desc->padding.left());
     162    style->setPaddingRight(desc->padding.right());
     163}
     164
     165RenderThemeEfl::ThemePartCacheEntry::ThemePartCacheEntry()
     166    : ee(0), o(0), surface(0)
     167{
     168}
     169
     170RenderThemeEfl::ThemePartCacheEntry::~ThemePartCacheEntry()
     171{
     172    if (surface)
     173        cairo_surface_destroy(surface);
     174    if (o)
     175        evas_object_del(o);
     176    if (ee)
     177        ecore_evas_free(ee);
     178}
     179
     180static cairo_surface_t* createCairoSurfaceFor(Ecore_Evas* ee)
     181{
     182    ASSERT(ee);
     183
     184    int width, height;
     185    ecore_evas_geometry_get(ee, 0, 0, &width, &height);
     186    ASSERT(width > 0 && height > 0);
     187
     188    unsigned char* buffer = static_cast<unsigned char*>(const_cast<void*>(ecore_evas_buffer_pixels_get(ee)));
     189    cairo_surface_t* surface = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, width, height, width * 4);
     190
     191    cairo_status_t status = cairo_surface_status(surface);
     192    if (status != CAIRO_STATUS_SUCCESS) {
     193        EINA_LOG_ERR("Could not create cairo surface: %s", cairo_status_to_string(status));
     194        return 0;
     195    }
     196
     197    return surface;
     198}
     199
     200static bool isFormElementTooLargeToDisplay(const IntSize& elementSize)
     201{
     202    // This limit of 20000 pixels is hardcoded inside edje -- anything above this size
     203    // will be clipped. This value seems to be reasonable enough so that hardcoding it
     204    // here won't be a problem.
     205    static const int maxEdjeDimension = 20000;
     206
     207    return elementSize.width() > maxEdjeDimension || elementSize.height() > maxEdjeDimension;
     208}
     209
     210RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::ThemePartCacheEntry::create(const String& themePath, FormType type, const IntSize& size)
     211{
     212    ASSERT(!themePath.isEmpty());
     213    ASSERT(!size.isEmpty());
     214
     215    if (isFormElementTooLargeToDisplay(size)) {
     216        EINA_LOG_ERR("Cannot render an element of size %dx%d.", size.width(), size.height());
     217        return 0;
     218    }
     219
     220    OwnPtr<ThemePartCacheEntry*> entry = adoptPtr(new ThemePartCacheEntry);
     221
     222    entry->ee = ecore_evas_buffer_new(size.width(), size.height());
     223    if (!entry->ee) {
     224        EINA_LOG_ERR("ecore_evas_buffer_new(%d, %d) failed.", size.width(), size.height());
     225        return 0;
     226    }
     227
     228    // By default EFL creates buffers without alpha.
     229    ecore_evas_alpha_set(entry->ee, EINA_TRUE);
     230
     231    entry->o = edje_object_add(ecore_evas_get(entry->ee));
     232    ASSERT(entry->o);
     233
     234    if (!setSourceGroupForEdjeObject(entry->o, themePath, toEdjeGroup(type)))
     235        return 0;
     236
     237    entry->surface = createCairoSurfaceFor(entry->ee);
     238    if (!entry->surface)
     239        return 0;
     240
     241    evas_object_resize(entry->o, size.width(), size.height());
     242    evas_object_show(entry->o);
     243
     244    entry->type = type;
     245    entry->size = size;
     246
     247    return entry.leakPtr();
     248}
     249
     250void RenderThemeEfl::ThemePartCacheEntry::reuse(const String& themePath, FormType newType, const IntSize& newSize)
     251{
     252    ASSERT(!themePath.isEmpty());
     253
     254    if (!newSize.isEmpty()) {
     255        cairo_surface_finish(surface);
     256
     257        size = newSize;
     258        ecore_evas_resize(ee, newSize.width(), newSize.height());
     259        evas_object_resize(o, newSize.width(), newSize.height());
     260
     261        surface = createCairoSurfaceFor(ee);
     262        if (!surface) {
     263            type = FormTypeLast; // Invalidate;
     264            return;
     265        }
     266    }
     267
     268    if (!setSourceGroupForEdjeObject(o, themePath, toEdjeGroup(newType))) {
     269        type = FormTypeLast; // Invalidate.
     270        return;
     271    }
     272
     273    type = newType;
     274}
     275
     276RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::getThemePartFromCache(FormType type, const IntSize& size)
     277{
     278    Vector<ThemePartCacheEntry*>::iterator it, end;
     279    size_t lastWithRequestedSize = notFound;
     280
     281    it = m_partCache.begin();
     282    end = m_partCache.end();
     283    for (size_t i = 0; it != end; i++, it++) {
     284        ThemePartCacheEntry* entry = *it;
     285        if (entry->size == size) {
     286            if (entry->type == type)
     287                return entry;
     288            lastWithRequestedSize = i;
     289        }
     290    }
     291
     292    if (m_partCache.size() < RENDER_THEME_EFL_PART_CACHE_MAX) {
     293        ThemePartCacheEntry* entry = ThemePartCacheEntry::create(themePath(), type, size);
     294        m_partCache.prepend(entry);
     295        return entry;
     296    }
     297
     298    // We have a full cache now!
     299    EINA_LOG_INFO("RenderTheme cache is full, reusing.");
     300
     301    if (lastWithRequestedSize != notFound && lastWithRequestedSize != 1) {
     302        ThemePartCacheEntry* entry = m_partCache.at(lastWithRequestedSize);
     303        entry->reuse(themePath(), type);
     304        m_partCache.remove(lastWithRequestedSize);
     305        m_partCache.prepend(entry);
     306        return entry;
     307    }
     308
     309    ThemePartCacheEntry* entry = m_partCache.last();
     310    entry->reuse(themePath(), type, size);
     311    m_partCache.removeLast();
     312    m_partCache.prepend(entry);
     313    return entry;
     314}
     315
     316void RenderThemeEfl::flushThemePartCache()
     317{
     318    Vector<ThemePartCacheEntry*>::iterator it, end;
     319
     320    it = m_partCache.begin();
     321    end = m_partCache.end();
     322    for (; it != end; it++)
     323        delete (*it);
     324
     325    m_partCache.clear();
     326}
     327
     328void RenderThemeEfl::applyEdjeStateFromForm(Evas_Object* object, ControlStates states)
     329{
     330    const char *signals[] = { // keep in sync with WebCore/platform/ThemeTypes.h
     331        "hovered",
     332        "pressed",
     333        "focused",
     334        "enabled",
     335        "checked",
     336        "read-only",
     337        "default",
     338        "window-inactive",
     339        "indeterminate",
     340        "spinup"
     341    };
     342
     343    edje_object_signal_emit(object, "reset", "");
     344
     345    for (size_t i = 0; i < WTF_ARRAY_LENGTH(signals); ++i) {
     346        if (states & (1 << i))
     347            edje_object_signal_emit(object, signals[i], "");
     348    }
     349}
     350
     351bool RenderThemeEfl::paintThemePart(RenderObject* object, FormType type, const PaintInfo& info, const IntRect& rect)
     352{
     353    loadThemeIfNeeded();
     354    _ASSERT_ON_RELEASE_RETURN_VAL(m_edje, false, "Could not paint native HTML part due to missing theme.");
     355
     356    ThemePartCacheEntry* entry;
     357    Eina_List* updates;
     358    cairo_t* cairo;
     359
     360    entry = getThemePartFromCache(type, rect.size());
     361    if (!entry)
     362        return false;
     363
     364    applyEdjeStateFromForm(entry->o, controlStatesForRenderer(object));
     365
     366    cairo = info.context->platformContext()->cr();
     367    ASSERT(cairo);
     368
     369    // Currently, only sliders needs this message; if other widget ever needs special
     370    // treatment, move them to special functions.
     371    if (type == SliderVertical || type == SliderHorizontal) {
     372        if (!object->isSlider())
     373            return true; // probably have -webkit-appearance: slider..
     374
     375        RenderSlider* renderSlider = toRenderSlider(object);
     376        HTMLInputElement* input = renderSlider->node()->toInputElement();
     377        double valueRange = input->maximum() - input->minimum();
     378
     379        OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
     380        Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
     381        msg->count = 2;
     382
     383        // The first parameter of the message decides if the progress bar
     384        // grows from the end of the slider or from the beginning. On vertical
     385        // sliders, it should always be the same and will not be affected by
     386        // text direction settings.
     387        if (object->style()->direction() == RTL || type == SliderVertical)
     388            msg->val[0] = 1;
     389        else
     390            msg->val[0] = 0;
     391
     392        msg->val[1] = (input->valueAsNumber() - input->minimum()) / valueRange;
     393        edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
     394#if ENABLE(PROGRESS_ELEMENT)
     395    } else if (type == ProgressBar) {
     396        RenderProgress* renderProgress = toRenderProgress(object);
     397
     398        int max = rect.width();
     399        double value = renderProgress->position();
     400
     401        OwnArrayPtr<char> buffer = adoptArrayPtr(new char[sizeof(Edje_Message_Float_Set) + sizeof(double)]);
     402        Edje_Message_Float_Set* msg = new(buffer.get()) Edje_Message_Float_Set;
     403        msg->count = 2;
     404
     405        if (object->style()->direction() == RTL)
     406            msg->val[0] = (1.0 - value) * max;
     407        else
     408            msg->val[0] = 0;
     409        msg->val[1] = value;
     410        edje_object_message_send(entry->o, EDJE_MESSAGE_FLOAT_SET, 0, msg);
     411#endif
     412    }
     413
     414    edje_object_calc_force(entry->o);
     415    edje_object_message_signal_process(entry->o);
     416    updates = evas_render_updates(ecore_evas_get(entry->ee));
     417    evas_render_updates_free(updates);
     418
     419    cairo_save(cairo);
     420    cairo_set_source_surface(cairo, entry->surface, rect.x(), rect.y());
     421    cairo_paint_with_alpha(cairo, 1.0);
     422    cairo_restore(cairo);
     423
     424    return false;
     425}
     426
     427PassRefPtr<RenderTheme> RenderThemeEfl::create(Page* page)
     428{
     429    return adoptRef(new RenderThemeEfl(page));
     430}
     431
     432PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
     433{
     434    if (page)
     435        return RenderThemeEfl::create(page);
     436
     437    static RenderTheme* fallback = RenderThemeEfl::create(0).leakRef();
     438    return fallback;
     439}
     440
     441static void applyColorCallback(void* data, Evas_Object*, const char* /* signal */, const char* colorClass)
     442{
     443    RenderThemeEfl* that = static_cast<RenderThemeEfl*>(data);
     444    that->setColorFromThemeClass(colorClass);
     445    that->platformColorsDidChange(); // Triggers relayout.
     446}
     447
     448static void fillColorsFromEdjeClass(Evas_Object* o, const char* colorClass, Color* color1, Color* color2 = 0, Color* color3 = 0)
     449{
     450    int r1, g1, b1, a1;
     451    int r2, g2, b2, a2;
     452    int r3, g3, b3, a3;
     453
     454    bool ok = edje_object_color_class_get(o, colorClass, &r1, &g1, &b1, &a1, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
     455    _ASSERT_ON_RELEASE_RETURN(ok, "Could not get color class '%s'\n", colorClass);
     456
     457    if (color1)
     458        color1->setRGB(makeRGBA(r1, g1, b1, a1));
     459    if (color2)
     460        color2->setRGB(makeRGBA(r2, g2, b2, a2));
     461    if (color3)
     462        color3->setRGB(makeRGBA(r3, g3, b3, a3));
     463}
     464
     465void RenderThemeEfl::setColorFromThemeClass(const char* colorClass)
     466{
     467    ASSERT(m_edje);
     468
     469    if (!strcmp("webkit/selection/active", colorClass))
     470        fillColorsFromEdjeClass(m_edje, colorClass, &m_activeSelectionForegroundColor, &m_activeSelectionBackgroundColor);
     471    else if (!strcmp("webkit/selection/inactive", colorClass))
     472        fillColorsFromEdjeClass(m_edje, colorClass, &m_inactiveSelectionForegroundColor, &m_inactiveSelectionBackgroundColor);
     473    else if (!strcmp("webkit/focus_ring", colorClass)) {
     474        fillColorsFromEdjeClass(m_edje, colorClass, &m_focusRingColor);
     475        // platformFocusRingColor() is only used for the default theme (without page)
     476        // The following is ugly, but no other way to do it unless we change it to use page themes as much as possible.
     477        RenderTheme::setCustomFocusRingColor(m_focusRingColor);
     478    }
     479}
     480
     481void RenderThemeEfl::setThemePath(const String& path)
     482{
     483    if (path == m_themePath)
     484        return;
     485
     486    if (path.isEmpty()) {
     487        EINA_LOG_CRIT("No valid theme defined, things will not work properly.");
     488        return;
     489    }
     490
     491    m_themePath = path;
     492
     493    loadTheme();
     494}
     495
     496String RenderThemeEfl::themePath() const
     497{
     498#if !NDEBUG
     499    if (m_edje) {
     500        const char* path;
     501        edje_object_file_get(o, &path, 0);
     502        ASSERT(m_themePath == path);
     503    }
     504#endif
     505    return m_themePath;
     506}
     507
     508bool RenderThemeEfl::loadTheme()
     509{
     510    ASSERT(!m_themePath.isEmpty());
     511
     512    if (!m_canvas) {
     513        m_canvas = ecore_evas_buffer_new(1, 1);
     514        _ASSERT_ON_RELEASE_RETURN_VAL(m_canvas, false,
     515                "Could not create canvas required by theme, things will not work properly.");
     516    }
     517
     518    Evas_Object* o = edje_object_add(ecore_evas_get(m_canvas));
     519    _ASSERT_ON_RELEASE_RETURN_VAL(o, false, "Could not create new base Edje object.");
     520
     521    if (!setSourceGroupForEdjeObject(o, m_themePath, "webkit/base")) {
     522        evas_object_del(o);
     523        return false; // Keep current theme.
     524    }
     525
     526    // Get rid of existing theme.
     527    if (m_edje) {
     528        flushThemePartCache();
     529        evas_object_del(m_edje);
     530    }
     531
     532    // Set new loaded theme, and apply it.
     533    m_edje = o;
     534
     535    edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/selection/active", applyColorCallback, this);
     536    edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/selection/inactive", applyColorCallback, this);
     537    edje_object_signal_callback_add(m_edje, "color_class,set", "webkit/focus_ring", applyColorCallback, this);
     538
     539    applyPartDescriptionsFrom(m_themePath);
     540
     541    setColorFromThemeClass("webkit/selection/active");
     542    setColorFromThemeClass("webkit/selection/inactive");
     543    setColorFromThemeClass("webkit/focus_ring");
     544
     545    platformColorsDidChange(); // Schedules a relayout, do last.
     546
     547    return true;
     548}
     549
     550void RenderThemeEfl::applyPartDescriptionFallback(ThemePartDesc* desc)
     551{
     552    desc->min.setWidth(Length(0, Fixed));
     553    desc->min.setHeight(Length(0, Fixed));
     554
     555    desc->max.setWidth(Length(0, Fixed));
     556    desc->max.setHeight(Length(0, Fixed));
     557
     558    desc->padding = LengthBox(0, 0, 0, 0);
     559}
     560
     561void RenderThemeEfl::applyPartDescription(Evas_Object* object, ThemePartDesc* desc)
     562{
     563    Evas_Coord minw, minh, maxw, maxh;
     564
     565    edje_object_size_min_get(object, &minw, &minh);
     566    if (!minw && !minh)
     567        edje_object_size_min_calc(object, &minw, &minh);
     568
     569    desc->min.setWidth(Length(minw, Fixed));
     570    desc->min.setHeight(Length(minh, Fixed));
     571
     572    edje_object_size_max_get(object, &maxw, &maxh);
     573    desc->max.setWidth(Length(maxw, Fixed));
     574    desc->max.setHeight(Length(maxh, Fixed));
     575
     576    if (!edje_object_part_exists(object, "text_confinement"))
     577        desc->padding = LengthBox(0, 0, 0, 0);
     578    else {
     579        Evas_Coord px, py, pw, ph;
     580        Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0;
     581        int t, r, b, l;
     582
     583        if (minw > 0)
     584            ow = minw;
     585        else
     586            ow = 100;
     587        if (minh > 0)
     588            oh = minh;
     589        else
     590            oh = 100;
     591        if (maxw > 0 && ow > maxw)
     592            ow = maxw;
     593        if (maxh > 0 && oh > maxh)
     594            oh = maxh;
     595
     596        evas_object_move(object, ox, oy);
     597        evas_object_resize(object, ow, oh);
     598        edje_object_calc_force(object);
     599        edje_object_message_signal_process(object);
     600        edje_object_part_geometry_get(object, "text_confinement", &px, &py, &pw, &ph);
     601
     602        t = py - oy;
     603        b = (oh + oy) - (ph + py);
     604
     605        l = px - ox;
     606        r = (ow + ox) - (pw + px);
     607
     608        desc->padding = LengthBox(t, r, b, l);
     609    }
     610}
     611
     612void RenderThemeEfl::applyPartDescriptionsFrom(const String& themePath)
     613{
     614    Evas_Object* temp = edje_object_add(ecore_evas_get(m_canvas));
     615    _ASSERT_ON_RELEASE_RETURN(temp, "Could not create Edje object.");
     616
     617    for (size_t i = 0; i < FormTypeLast; i++) {
    631618        FormType type = static_cast<FormType>(i);
    632         const char* group = edjeGroupFromFormType(type);
    633619        m_partDescs[i].type = type;
    634         if (!edje_object_file_set(object, file, group)) {
    635             Edje_Load_Error err = edje_object_load_error_get(object);
    636             const char* errmsg = edje_load_error_str(err);
    637             EINA_LOG_ERR("Could not set theme group '%s' of file '%s': %s",
    638                          group, file, errmsg);
    639 
     620        if (!setSourceGroupForEdjeObject(temp, themePath, toEdjeGroup(type)))
    640621            applyPartDescriptionFallback(m_partDescs + i);
    641         } else
    642             applyPartDescription(object, m_partDescs + i);
    643     }
    644     evas_object_del(object);
     622        else
     623            applyPartDescription(temp, m_partDescs + i);
     624    }
     625
     626    evas_object_del(temp);
    645627}
    646628
     
    665647RenderThemeEfl::~RenderThemeEfl()
    666648{
    667     cacheThemePartFlush();
     649    flushThemePartCache();
    668650
    669651    if (m_canvas) {
     
    835817
    836818    adjustSizeConstraints(style, CheckBox);
    837     ASSERT(m_edje);
    838819
    839820    style->resetBorder();
    840821
    841     const struct ThemePartDesc *desc = m_partDescs + (size_t)CheckBox;
     822    const ThemePartDesc* desc = m_partDescs + (size_t)CheckBox;
    842823    if (style->width().value() < desc->min.width().value())
    843824        style->setWidth(desc->min.width());
     
    859840
    860841    adjustSizeConstraints(style, RadioButton);
    861     ASSERT(m_edje);
    862842
    863843    style->resetBorder();
    864844
    865     const struct ThemePartDesc *desc = m_partDescs + (size_t)RadioButton;
     845    const ThemePartDesc* desc = m_partDescs + (size_t)RadioButton;
    866846    if (style->width().value() < desc->min.width().value())
    867847        style->setWidth(desc->min.width());
     
    10901070    _ASSERT_ON_RELEASE_RETURN_VAL(m_edje, false, "Could not paint native HTML part due to missing theme.");
    10911071
    1092     ThemePartCacheEntry* entry;
    1093 
    1094     entry = cacheThemePartGet(formType, rect.size());
     1072    ThemePartCacheEntry* entry = getThemePartFromCache(formType, rect.size());
    10951073    _ASSERT_ON_RELEASE_RETURN_VAL(entry, false, "Could not paint native HTML part due to missing theme part.");
    10961074
  • trunk/Source/WebCore/platform/efl/RenderThemeEfl.h

    r128049 r128274  
    211211
    212212    void setThemePath(const String&);
    213     String themePath() { return m_themePath; }
     213    String themePath() const;
    214214
    215215protected:
     
    220220    ALWAYS_INLINE bool loadThemeIfNeeded() const
    221221    {
    222         return m_edje || const_cast<RenderThemeEfl*>(this)->loadTheme();
     222        return m_edje || (!m_themePath.isEmpty() && const_cast<RenderThemeEfl*>(this)->loadTheme());
    223223    }
    224224
    225     void applyPartDescriptionsFrom(Evas_Object*);
    226 
    227     const char* edjeGroupFromFormType(FormType) const;
     225    void applyPartDescriptionsFrom(const String& themePath);
     226
    228227    void applyEdjeStateFromForm(Evas_Object*, ControlStates);
    229228    bool paintThemePart(RenderObject*, FormType, const PaintInfo&, const IntRect&);
    230     bool isFormElementTooLargeToDisplay(const IntSize&);
    231229
    232230#if ENABLE(VIDEO)
     
    261259
    262260    struct ThemePartCacheEntry {
     261        ThemePartCacheEntry();
     262        ~ThemePartCacheEntry();
     263        static ThemePartCacheEntry* create(const String& themePath, FormType, const IntSize&);
     264        void reuse(const String& themePath, FormType, const IntSize& = IntSize());
     265
    263266        FormType type;
    264267        IntSize size;
     
    272275    // this should be small and not so frequently used,
    273276    // so use a vector and do linear searches
    274     Vector<struct ThemePartCacheEntry *> m_partCache;
    275 
    276     // get (use, create or replace) entry from cache
    277     struct ThemePartCacheEntry* cacheThemePartGet(FormType, const IntSize&);
    278     // flush cache, deleting all entries
    279     void cacheThemePartFlush();
    280 
    281     // internal, used by cacheThemePartGet()
    282     bool themePartCacheEntryReset(struct ThemePartCacheEntry*, FormType);
    283     bool themePartCacheEntrySurfaceCreate(struct ThemePartCacheEntry*);
    284     struct ThemePartCacheEntry* cacheThemePartNew(FormType, const IntSize&);
    285     struct ThemePartCacheEntry* cacheThemePartReset(FormType, struct ThemePartCacheEntry*);
    286     struct ThemePartCacheEntry* cacheThemePartResizeAndReset(FormType, const IntSize&, struct ThemePartCacheEntry*);
    287 
     277    Vector<ThemePartCacheEntry*> m_partCache;
     278
     279    ThemePartCacheEntry* getThemePartFromCache(FormType, const IntSize&);
     280    void flushThemePartCache();
    288281};
    289282}
Note: See TracChangeset for help on using the changeset viewer.