diff --git a/src/bin/edje/edje_cc_handlers.c b/src/bin/edje/edje_cc_handlers.c index dd0b4cc2cb..b1b07a4328 100644 --- a/src/bin/edje/edje_cc_handlers.c +++ b/src/bin/edje/edje_cc_handlers.c @@ -497,6 +497,7 @@ static void st_collections_group_parts_part_description_map_perspective_on static void st_collections_group_parts_part_description_map_color(void); static void st_collections_group_parts_part_description_map_zoom_x(void); static void st_collections_group_parts_part_description_map_zoom_y(void); +static void st_collections_group_parts_part_description_map_zoom_center(void); static void st_collections_group_parts_part_description_perspective_zplane(void); static void st_collections_group_parts_part_description_perspective_focal(void); static void st_collections_group_parts_part_api(void); @@ -1032,6 +1033,7 @@ New_Statement_Handler statement_handlers[] = {"collections.group.parts.part.description.map.color", st_collections_group_parts_part_description_map_color}, {"collections.group.parts.part.description.map.zoom.x", st_collections_group_parts_part_description_map_zoom_x}, {"collections.group.parts.part.description.map.zoom.y", st_collections_group_parts_part_description_map_zoom_y}, + {"collections.group.parts.part.description.map.zoom.center", st_collections_group_parts_part_description_map_zoom_center}, {"collections.group.parts.part.description.perspective.zplane", st_collections_group_parts_part_description_perspective_zplane}, {"collections.group.parts.part.description.perspective.focal", st_collections_group_parts_part_description_perspective_focal}, {"collections.group.parts.part.description.params.int", st_collections_group_parts_part_description_params_int}, @@ -6464,6 +6466,7 @@ _part_desc_free(Edje_Part_Collection *pc, part_lookup_del(pc, &(ed->map.id_persp)); part_lookup_del(pc, &(ed->map.id_light)); part_lookup_del(pc, &(ed->map.rot.id_center)); + part_lookup_del(pc, &(ed->map.zoom.id_center)); switch (ep->type) { @@ -8617,6 +8620,7 @@ ob_collections_group_parts_part_description(void) ed->map.id_persp = -1; ed->map.id_light = -1; ed->map.rot.id_center = -1; + ed->map.zoom.id_center = -1; ed->map.rot.x = FROM_DOUBLE(0.0); ed->map.rot.y = FROM_DOUBLE(0.0); ed->map.rot.z = FROM_DOUBLE(0.0); @@ -8776,6 +8780,7 @@ st_collections_group_parts_part_description_inherit(void) data_queue_copied_part_lookup(pc, &parent->map.id_persp, &ed->map.id_persp); data_queue_copied_part_lookup(pc, &parent->map.id_light, &ed->map.id_light); data_queue_copied_part_lookup(pc, &parent->map.rot.id_center, &ed->map.rot.id_center); + data_queue_copied_part_lookup(pc, &parent->map.zoom.id_center, &ed->map.zoom.id_center); /* make sure all the allocated memory is getting copied, not just * referenced @@ -14313,6 +14318,57 @@ st_collections_group_parts_part_description_map_light(void) } } +/** @edcsubsection{collections_group_parts_description_map_zoom, + * Group.Parts.Part.Description.Map.Zoom} */ + +/** + @page edcref + @block + rotation + @context + map { + .. + zoom { + center: "name"; + x: 1.0; + y: 1.0; + } + .. + } + @description + Zooms the part, optionally from the center on another part. + @endblock + + @property + center + @parameters + [another part's name] + @effect + This sets the part that is used as the center of zoom when + zooming the part with this description. The part's center point + is used as the zoom center when applying zoom from the + x and y axes. If no center is given, the parts original center + itself is used for the zoom center. + @endproperty +*/ +static void +st_collections_group_parts_part_description_map_zoom_center(void) +{ + Edje_Part_Collection *pc; + + check_arg_count(1); + + pc = eina_list_data_get(eina_list_last(edje_collections)); + + { + char *name; + + name = parse_str(0); + data_queue_part_lookup(pc, name, &(current_desc->map.zoom.id_center)); + free(name); + } +} + /** @page edcref @property diff --git a/src/bin/elementary/test_ui_spotlight.c b/src/bin/elementary/test_ui_spotlight.c index 589220b8e8..bcb6fbbd3e 100644 --- a/src/bin/elementary/test_ui_spotlight.c +++ b/src/bin/elementary/test_ui_spotlight.c @@ -299,7 +299,8 @@ pack_btn_cb(void *data, const Efl_Event *ev EINA_UNUSED) index = efl_ui_range_value_get(param->pack_sp); if (index > cnt) efl_ui_range_value_set(param->pack_sp, cnt); - efl_ui_range_limits_set(param->pack_sp, 0, cnt); + if (cnt > 0) + efl_ui_range_limits_set(param->pack_sp, 0, cnt); if (cnt > 0) { @@ -310,7 +311,8 @@ pack_btn_cb(void *data, const Efl_Event *ev EINA_UNUSED) index = efl_ui_range_value_get(param->unpack_sp); if (index > cnt) efl_ui_range_value_set(param->unpack_sp, cnt); - efl_ui_range_limits_set(param->unpack_sp, 0, cnt); + if (cnt > 0) + efl_ui_range_limits_set(param->unpack_sp, 0, cnt); } else { @@ -502,6 +504,7 @@ pack_cb(void *data, Eo *spotlight = params->spotlight; Eo *btn, *box, *in_box1, *in_box2, *sp1, *sp2; Pack_Params *pack_param; + int num; btn = efl_add(EFL_UI_BUTTON_CLASS, navi, efl_text_set(efl_added, "Back"), @@ -517,11 +520,13 @@ pack_cb(void *data, efl_gfx_arrangement_content_padding_set(efl_added, 10, 10, EINA_TRUE), efl_ui_layout_orientation_set(efl_added, EFL_UI_LAYOUT_ORIENTATION_HORIZONTAL)); - sp1 = efl_add(EFL_UI_SPIN_BUTTON_CLASS, in_box1, - efl_ui_range_limits_set(efl_added, 0, - efl_content_count(spotlight)), - efl_ui_range_value_set(efl_added, - efl_ui_spotlight_active_index_get(spotlight))); + sp1 = efl_add(EFL_UI_SPIN_BUTTON_CLASS, in_box1); + num = efl_content_count(spotlight); + if (num) + efl_ui_range_limits_set(sp1, 0, num); + num = efl_ui_spotlight_active_index_get(spotlight); + if (num >= 0) + efl_ui_range_value_set(sp1, num); in_box2 = efl_add(EFL_UI_BOX_CLASS, box, efl_gfx_arrangement_content_padding_set(efl_added, 10, 10, EINA_TRUE), diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh index ac072a4220..a672d209b4 100644 --- a/src/bin/eolian_mono/eolian/mono/documentation.hh +++ b/src/bin/eolian_mono/eolian/mono/documentation.hh @@ -11,6 +11,8 @@ #include +static const std::string BETA_REF_SUFFIX = " (object still in beta stage)"; + namespace eolian_mono { struct documentation_generator @@ -128,32 +130,38 @@ struct documentation_generator } // Turns an Eolian reference like @Efl.Input.Pointer.tool into a tag - static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail) + static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail, + bool want_beta) { const Eolian_Object *data, *data2; ::Eolian_Object_Type type = ::eolian_doc_token_ref_resolve(token, state, &data, &data2); std::string ref; + bool is_beta = false; switch(type) { case ::EOLIAN_OBJECT_STRUCT_FIELD: ref = name_helpers::managed_namespace(::eolian_object_name_get(data)); ref += "."; ref += ::eolian_object_name_get(data2); + is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); if (blacklist::is_struct_blacklisted(ref)) return ""; break; case ::EOLIAN_OBJECT_EVENT: ref = object_ref_conversion(data); ref += "."; ref += name_helpers::managed_event_name(::eolian_object_name_get(data2)); + is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); break; case ::EOLIAN_OBJECT_ENUM_FIELD: ref = name_helpers::managed_namespace(::eolian_object_name_get(data)); ref += "."; ref += name_helpers::enum_field_managed_name(::eolian_object_name_get(data2)); + is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); break; case ::EOLIAN_OBJECT_FUNCTION: ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail); + is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); break; case ::EOLIAN_OBJECT_VARIABLE: if (::eolian_variable_type_get((::Eolian_Variable *)data) == ::EOLIAN_VAR_CONSTANT) @@ -173,16 +181,21 @@ struct documentation_generator break; case ::EOLIAN_OBJECT_CLASS: ref = object_ref_conversion(data); + is_beta = eolian_object_is_beta(data); break; default: ref = name_helpers::managed_namespace(::eolian_object_name_get(data)); + is_beta = eolian_object_is_beta(data); break; } + + if (!ref.empty() && !want_beta && is_beta) + ref += BETA_REF_SUFFIX; return ref; } // Turns EO documentation syntax into C# triple-slash XML comment syntax - static std::string syntax_conversion(std::string text, const Eolian_State *state) + static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta) { std::string new_text, ref; ::Eolian_Doc_Token token; @@ -213,9 +226,14 @@ struct documentation_generator new_text += token_text; break; case ::EOLIAN_DOC_TOKEN_REF: - ref = ref_conversion(&token, state, name_tail); + ref = ref_conversion(&token, state, name_tail, want_beta); if (ref != "") - new_text += ""; + { + if (utils::ends_with(ref, BETA_REF_SUFFIX)) + new_text += "" + ref + ""; + else + new_text += ""; + } else // Unresolved references are passed through. // They will appear in the docs as plain text, without link, @@ -264,7 +282,8 @@ struct documentation_generator std::string new_text; if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context)) return false; - new_text = syntax_conversion( new_text, context_find_tag(context).state ); + auto options = context_find_tag(context); + new_text = syntax_conversion( new_text, context_find_tag(context).state, options.want_beta); std::string tabs; as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context); @@ -486,8 +505,18 @@ struct documentation_generator for (auto &¶m : ctor.function.parameters) { + auto ref = function_conversion(func); + + if (!context_find_tag(context).want_beta && func.is_beta) + { + ref += BETA_REF_SUFFIX; + ref = "" + ref + ""; + } + else + ref = ""; + if (!as_generator( - scope_tab << "/// " << summary << " See \n" + scope_tab << "/// " << summary << " See " << ref << "\n" ).generate(sink, param, context)) return false; } diff --git a/src/bin/eolian_mono/eolian/mono/enum_definition.hh b/src/bin/eolian_mono/eolian/mono/enum_definition.hh index 922463936e..4dae3cc7aa 100644 --- a/src/bin/eolian_mono/eolian/mono/enum_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/enum_definition.hh @@ -25,6 +25,7 @@ struct enum_definition_generator if(!as_generator ( + "[Efl.Eo.BindingEntity]\n" "public enum " << string << "\n{\n" ) .generate(sink, name_helpers::typedecl_managed_name(enum_), context)) diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh index c1a45033f9..ef4f5f4dbd 100644 --- a/src/bin/eolian_mono/eolian/mono/events.hh +++ b/src/bin/eolian_mono/eolian/mono/events.hh @@ -1,5 +1,5 @@ #ifndef EOLIAN_MONO_EVENTS_HH -#define EOLINA_MONO_EVENTS_HH +#define EOLIAN_MONO_EVENTS_HH #include @@ -250,6 +250,7 @@ struct event_argument_wrapper_generator return as_generator("///Event argument wrapper for event .\n" + << "[Efl.Eo.BindingEntity]\n" << "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n" << scope_tab << "///Actual event payload.\n" << scope_tab << "public " << type << " arg { get; set; }\n" diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh index f724d8029e..721368f115 100644 --- a/src/bin/eolian_mono/eolian/mono/function_pointer.hh +++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh @@ -44,6 +44,7 @@ struct function_pointer { // C# visible delegate if (!as_generator(documentation + << "[Efl.Eo.BindingEntity]\n" << "public delegate " << type << " " << string << "(" << (parameter % ", ") << ");\n") .generate(sink, std::make_tuple(f, f.return_type, f_name, f.parameters), funcptr_ctx)) diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh index dc72696342..985e3739d9 100644 --- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh +++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh @@ -21,6 +21,16 @@ struct class_context }; wrapper_kind current_wrapper_kind; std::string name; + + class_context(wrapper_kind current_wrapper_kind) + : current_wrapper_kind(current_wrapper_kind) + , name() + {} + + class_context(wrapper_kind current_wrapper_kind, std::string const& name) + : current_wrapper_kind(current_wrapper_kind) + , name(name) + {} }; struct indentation_context diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh index dffb38b820..c3e1114c98 100644 --- a/src/bin/eolian_mono/eolian/mono/helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -3,6 +3,7 @@ #include "grammar/klass_def.hpp" #include "blacklist.hh" +#include "generation_contexts.hh" #include "name_helpers.hh" namespace eolian_mono { @@ -165,11 +166,19 @@ bool has_regular_ancestor(attributes::klass_def const& cls) /* * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself) */ -std::vector get_all_implementable_methods(attributes::klass_def const& cls) +template +std::vector get_all_implementable_methods(attributes::klass_def const& cls, Context const& context) { + bool want_beta = efl::eolian::grammar::context_find_tag(context).want_beta; std::vector ret; + auto filter_beta = [&want_beta](attributes::function_def const& func) { + if (!want_beta) + return !func.is_beta; + else + return true; + }; - std::copy(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret)); + std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter_beta); // Non implemented interfaces std::set implemented_interfaces; @@ -206,7 +215,7 @@ std::vector get_all_implementable_methods(attributes:: for (auto&& inherit : interfaces) { attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit); - std::copy(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret)); + std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter_beta); } return ret; diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index c34d7c06e0..a98866e34a 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -36,7 +36,7 @@ template static std::size_t get_implementable_function_count(grammar::attributes::klass_def const& cls, Context context) { - auto methods = helpers::get_all_implementable_methods(cls); + auto methods = helpers::get_all_implementable_methods(cls, context); return std::count_if(methods.cbegin(), methods.cend(), [&context](grammar::attributes::function_def const& func) { return !blacklist::is_function_blacklisted(func, context) && !func.is_static; @@ -106,6 +106,9 @@ struct klass .generate(sink, attributes::unused, iface_cxt)) return false; + if(!as_generator("[Efl.Eo.BindingEntity]\n").generate(sink, attributes::unused, iface_cxt)) + return false; + if(!as_generator ( "public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : " @@ -115,6 +118,9 @@ struct klass for(auto first = std::begin(cls.immediate_inherits) , last = std::end(cls.immediate_inherits); first != last; ++first) { + if (!context_find_tag(iface_cxt).want_beta && first->is_beta) + continue; + if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_) if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt)) return false; @@ -230,7 +236,7 @@ struct klass .generate(sink, cls.parts, concrete_cxt)) return false; // Concrete function definitions - auto implemented_methods = helpers::get_all_implementable_methods(cls); + auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt); if(!as_generator(*(function_definition)) .generate(sink, implemented_methods, concrete_cxt)) return false; @@ -276,6 +282,7 @@ struct klass ( documentation << "[" << name_helpers::klass_full_native_inherit_name(cls) << "]\n" + << "[Efl.Eo.BindingEntity]\n" << "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : " << (klass_full_concrete_or_interface_name % ",") // classes << (root ? "Efl.Eo.EoWrapper" : "") // ... or root @@ -302,7 +309,7 @@ struct klass .generate(sink, cls.parts, inherit_cxt)) return false; // Inherit function definitions - auto implemented_methods = helpers::get_all_implementable_methods(cls); + auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt); if(!as_generator(*(function_definition(true))) .generate(sink, implemented_methods, inherit_cxt)) return false; @@ -354,7 +361,7 @@ struct klass context); auto native_inherit_name = name_helpers::klass_native_inherit_name(cls); auto inherit_name = name_helpers::klass_inherit_name(cls); - auto implementable_methods = helpers::get_all_implementable_methods(cls); + auto implementable_methods = helpers::get_all_implementable_methods(cls, context); bool root = !helpers::has_regular_ancestor(cls); auto const& indent = current_indentation(inative_cxt); @@ -499,7 +506,7 @@ struct klass // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters. << scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n" << scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") : " - << "base(" << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n" + << "base(" << name_helpers::klass_get_name(cls) << "(), parent)\n" << scope_tab << "{\n" << (*(scope_tab << scope_tab << constructor_invocation << "\n")) << scope_tab << scope_tab << "FinishInstantiation();\n" @@ -539,9 +546,8 @@ struct klass scope_tab << "/// Initializes a new instance of the class.\n" << scope_tab << "/// Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.\n" << scope_tab << "/// The pointer to the base native Eo class.\n" - << scope_tab << "/// The managed type of the public constructor that originated this call.\n" << scope_tab << "/// The Efl.Object parent of this instance.\n" - << scope_tab << "protected " << inherit_name << "(IntPtr baseKlass, System.Type managedType, Efl.Object parent) : base(baseKlass, managedType, parent)\n" + << scope_tab << "protected " << inherit_name << "(IntPtr baseKlass, Efl.Object parent) : base(baseKlass, parent)\n" << scope_tab << "{\n" << scope_tab << "}\n\n" ).generate(sink, attributes::unused, context); diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh index d3fcbfa41e..ce16c9a374 100644 --- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh @@ -183,6 +183,7 @@ struct marshall_type_visitor_generate , is_out , is_return , is_ptr + , false , is_special_subtype }(r); } @@ -195,6 +196,7 @@ struct marshall_type_visitor_generate , is_out , is_return , is_ptr + , false , is_special_subtype }(regular); } @@ -208,6 +210,7 @@ struct marshall_type_visitor_generate , is_out , is_return , is_ptr + , false , is_special_subtype }(klass_name); } @@ -253,7 +256,7 @@ struct marshall_type_visitor_generate auto default_match = [&] (attributes::complex_type_def const& complex) { regular_type_def no_pointer_regular = complex.outer; - return visitor_type{sink, context, c_type, false}(no_pointer_regular) + return visitor_type{sink, context, c_type, false, false, false, false}(no_pointer_regular) && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context); }; @@ -286,6 +289,7 @@ struct marshall_type_visitor_generate , is_out , is_return , is_ptr + , false , is_special_subtype }(complex); } diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index 851b9c4025..c949783945 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh @@ -396,6 +396,7 @@ struct struct_definition_generator if(!as_generator ( indent << "[StructLayout(LayoutKind.Sequential)]\n" + << indent << "[Efl.Eo.BindingEntity]\n" << indent << "public struct " << string << "\n" << indent << "{\n" ) diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh index 41cdf92f19..abfa6e9db6 100644 --- a/src/bin/eolian_mono/eolian/mono/type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh @@ -412,7 +412,7 @@ struct visitor_generate // pointers.swap(no_pointer_regular.pointers); // if(is_out) // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); - return visitor_type{sink, context, c_type, false}(no_pointer_regular) + return visitor_type{sink, context, c_type, false, false, false, false, false}(no_pointer_regular) && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context) ; // && detail::generate_pointers(sink, pointers, *context, false); diff --git a/src/bindings/cxx/eina_cxx/eina_optional.hh b/src/bindings/cxx/eina_cxx/eina_optional.hh index 91b38c3290..70a5cc20e5 100644 --- a/src/bindings/cxx/eina_cxx/eina_optional.hh +++ b/src/bindings/cxx/eina_cxx/eina_optional.hh @@ -387,7 +387,15 @@ private: void _construct(U&& object) { assert(!is_engaged()); + // NOTE: the buffer memory is intended to be in an + // uninitialized state here. + // So this warning can be disabled. +#pragma GCC diagnostic push +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif new (&buffer) T(std::forward(object)); +#pragma GCC diagnostic pop engaged = true; } diff --git a/src/bindings/cxx/eldbus_cxx/eldbus_service.hh b/src/bindings/cxx/eldbus_cxx/eldbus_service.hh index 6a4919ccb8..31c3386bd3 100644 --- a/src/bindings/cxx/eldbus_cxx/eldbus_service.hh +++ b/src/bindings/cxx/eldbus_cxx/eldbus_service.hh @@ -293,11 +293,23 @@ void _create_methods_specification_impl(Method const& method, Eldbus_Method2& el eldbus::_fill_methods(*out_params, method.outs); + // NOTE: C pointer magic performed under the hood requires this conversion + // between incompatible function pointer types. + // C++ always raises a warning for such conversions, so this warning + // can be disabled just here. +#pragma GCC diagnostic push +#ifndef __clang__ +#pragma GCC diagnostic ignored "-Wcast-function-type" +#endif + Eldbus_Method_Cb method_cb = + reinterpret_cast + (static_cast + (&_method_callback)); +#pragma GCC diagnostic pop + eldbus_method = {{method.name, &(*in_params)[0], &(*out_params)[0] - , reinterpret_cast - (static_cast - (&_method_callback)) + , method_cb , ELDBUS_METHOD_FLAG_HAS_DATA} , new std::tuple ManagedToNative = new Dictionary(); private static Dictionary NativeToManaged = new Dictionary(); + private static Dictionary StandardToManaged = new Dictionary(); + private static Dictionary ManagedToStandard = new Dictionary(); private static bool TypesLoaded; // CLR defaults to false; public static ValueType GetManaged(IntPtr native) @@ -750,48 +753,106 @@ static class ValueTypeBridge return ManagedToNative[valueType]; } + /// Returns the Eina.Value type associated with the given C# type. + public static ValueType GetManaged(System.Type type) + { + ValueType v; + if (StandardToManaged.TryGetValue(type, out v)) + { + return v; + } + else + { + if (typeof(Efl.Object).IsAssignableFrom(type)) + { + return ValueType.Object; + } + throw new Efl.EflException($"Unknown value type mapping for C# type {type}"); + } + } + + /// Returns the System.Type associated with the given Eina.Value type. + /// The intermediate type as returned by . + /// The associated C# type with this value type. + public static System.Type GetStandard(ValueType valueType) + { + System.Type ret = null; + if (ManagedToStandard.TryGetValue(valueType, out ret)) + { + return ret; + } + else + { + throw new Efl.EflException($"Unknown C# type mapping for value type {valueType}"); + } + } + private static void LoadTypes() { Eina.Config.Init(); // Make sure eina is initialized. ManagedToNative.Add(ValueType.SByte, type_sbyte()); NativeToManaged.Add(type_sbyte(), ValueType.SByte); + StandardToManaged.Add(typeof(sbyte), ValueType.SByte); + ManagedToStandard.Add(ValueType.SByte, typeof(sbyte)); ManagedToNative.Add(ValueType.Byte, type_byte()); NativeToManaged.Add(type_byte(), ValueType.Byte); + StandardToManaged.Add(typeof(byte), ValueType.Byte); + ManagedToStandard.Add(ValueType.Byte, typeof(byte)); ManagedToNative.Add(ValueType.Short, type_short()); NativeToManaged.Add(type_short(), ValueType.Short); + StandardToManaged.Add(typeof(short), ValueType.Short); + ManagedToStandard.Add(ValueType.Short, typeof(short)); ManagedToNative.Add(ValueType.UShort, type_ushort()); NativeToManaged.Add(type_ushort(), ValueType.UShort); + StandardToManaged.Add(typeof(ushort), ValueType.UShort); + ManagedToStandard.Add(ValueType.UShort, typeof(ushort)); ManagedToNative.Add(ValueType.Int32, type_int32()); NativeToManaged.Add(type_int32(), ValueType.Int32); + StandardToManaged.Add(typeof(int), ValueType.Int32); + ManagedToStandard.Add(ValueType.Int32, typeof(int)); ManagedToNative.Add(ValueType.UInt32, type_uint32()); NativeToManaged.Add(type_uint32(), ValueType.UInt32); + StandardToManaged.Add(typeof(uint), ValueType.UInt32); + ManagedToStandard.Add(ValueType.UInt32, typeof(uint)); ManagedToNative.Add(ValueType.Long, type_long()); NativeToManaged.Add(type_long(), ValueType.Long); + ManagedToStandard.Add(ValueType.Long, typeof(long)); ManagedToNative.Add(ValueType.ULong, type_ulong()); NativeToManaged.Add(type_ulong(), ValueType.ULong); + ManagedToStandard.Add(ValueType.ULong, typeof(ulong)); ManagedToNative.Add(ValueType.Int64, type_int64()); NativeToManaged.Add(type_int64(), ValueType.Int64); + StandardToManaged.Add(typeof(long), ValueType.Int64); + ManagedToStandard.Add(ValueType.Int64, typeof(long)); ManagedToNative.Add(ValueType.UInt64, type_uint64()); NativeToManaged.Add(type_uint64(), ValueType.UInt64); + StandardToManaged.Add(typeof(ulong), ValueType.UInt64); + ManagedToStandard.Add(ValueType.UInt64, typeof(ulong)); ManagedToNative.Add(ValueType.Float, type_float()); NativeToManaged.Add(type_float(), ValueType.Float); + StandardToManaged.Add(typeof(float), ValueType.Float); + ManagedToStandard.Add(ValueType.Float, typeof(float)); ManagedToNative.Add(ValueType.Double, type_double()); NativeToManaged.Add(type_double(), ValueType.Double); + StandardToManaged.Add(typeof(double), ValueType.Double); + ManagedToStandard.Add(ValueType.Double, typeof(double)); ManagedToNative.Add(ValueType.String, type_string()); NativeToManaged.Add(type_string(), ValueType.String); + StandardToManaged.Add(typeof(string), ValueType.String); + ManagedToStandard.Add(ValueType.String, typeof(string)); ManagedToNative.Add(ValueType.Array, type_array()); NativeToManaged.Add(type_array(), ValueType.Array); @@ -804,9 +865,15 @@ static class ValueTypeBridge ManagedToNative.Add(ValueType.Error, type_error()); NativeToManaged.Add(type_error(), ValueType.Error); + StandardToManaged.Add(typeof(Eina.Error), ValueType.Error); + ManagedToStandard.Add(ValueType.Error, typeof(Eina.Error)); ManagedToNative.Add(ValueType.Object, type_object()); NativeToManaged.Add(type_object(), ValueType.Object); + // We don't use `typeof(Efl.Object)` directly in the StandartToManaged dictionary as typeof(myobj) may + // return a different type. For ManagedToStandard, we make use of C# generics covariance to create + // an collection of Efl.Objects when unwrapping. + ManagedToStandard.Add(ValueType.Object, typeof(Efl.Object)); ManagedToNative.Add(ValueType.Empty, IntPtr.Zero); NativeToManaged.Add(IntPtr.Zero, ValueType.Empty); @@ -916,7 +983,108 @@ public class Value : IDisposable, IComparable, IEquatable private Value() { this.Handle = Alloc(); + + if (this.Handle == IntPtr.Zero) + { + throw new OutOfMemoryException("Failed to allocate memory for Eina.Value"); + } + this.Ownership = Ownership.Managed; + MemoryNative.Memset(this.Handle, 0, eina_value_sizeof()); + } + + /// Creates a new Value from the given C# value. + /// The object to be wrapped. + public Value(object obj) : this() + { + var objType = obj.GetType(); + + if (objType == typeof(sbyte)) + { + Setup(ValueType.SByte); + Set((sbyte)obj); + } + else if (objType == typeof(byte)) + { + Setup(ValueType.Byte); + Set((byte)obj); + } + else if (objType == typeof(short)) + { + Setup(ValueType.Short); + Set((short)obj); + } + else if (objType == typeof(ushort)) + { + Setup(ValueType.UShort); + Set((ushort)obj); + } + else if (objType == typeof(int)) + { + Setup(ValueType.Int32); + Set((int)obj); + } + else if (objType == typeof(uint)) + { + Setup(ValueType.UInt32); + Set((uint)obj); + } + else if (objType == typeof(long)) + { + Setup(ValueType.Int64); + Set((long)obj); + } + else if (objType == typeof(ulong)) + { + Setup(ValueType.UInt64); + Set((ulong)obj); + } + else if (objType == typeof(float)) + { + Setup(ValueType.Float); + Set((float)obj); + } + else if (objType == typeof(double)) + { + Setup(ValueType.Double); + Set((double)obj); + } + else if (objType == typeof(string)) + { + Setup(ValueType.String); + Set(obj as string); + } + else if (typeof(Efl.Object).IsAssignableFrom(objType)) + { + Setup(ValueType.Object); + Set(obj as Efl.Object); + } + else + { + // Container type conversion is supported only from IEnumerable + if (!obj.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>))) + { + throw new ArgumentException($"Unsupported type for direct construction: {objType}"); + } + + Type[] genericArguments = objType.GetGenericArguments(); + if (genericArguments.Count() != 1) + { + throw new ArgumentException($"Unsupported type for direct construction: {objType}"); + } + + var genericArg = genericArguments[0]; + + var argValueType = ValueTypeBridge.GetManaged(genericArg); + + Setup(ValueType.Array, argValueType); + + foreach (var item in obj as System.Collections.IEnumerable) + { + Append(item); + } + + } } public Value(IntPtr handle, Ownership ownership = Ownership.Managed) @@ -1390,6 +1558,121 @@ public class Value : IDisposable, IComparable, IEquatable return b; } + /// Unwrap the value into its underlying C# value. + /// + /// Useful for methods like + /// as it will unpack the value to it correct C# type. + /// + /// The C# value wrapped by this value. + public object Unwrap() + { + switch (GetValueType()) + { + case ValueType.SByte: + { + sbyte o; + Get(out o); + return o; + } + case ValueType.Byte: + { + byte o; + Get(out o); + return o; + } + case ValueType.Short: + { + short o; + Get(out o); + return o; + } + case ValueType.UShort: + { + ushort o; + Get(out o); + return o; + } + case ValueType.Int32: + { + int o; + Get(out o); + return o; + } + case ValueType.UInt32: + { + uint o; + Get(out o); + return o; + } + case ValueType.Int64: + case ValueType.Long: + { + long o; + Get(out o); + return o; + } + case ValueType.UInt64: + case ValueType.ULong: + { + ulong o; + Get(out o); + return o; + } + case ValueType.Float: + { + float o; + Get(out o); + return o; + } + case ValueType.Double: + { + double o; + Get(out o); + return o; + } + case ValueType.String: + { + string o; + Get(out o); + return o; + } + case ValueType.Object: + { + Efl.Object o; + Get(out o); + return o; + } + case ValueType.Array: + case ValueType.List: + { + // Eina Array and Lists will be unwrapped into a System.Collections.Generic.List + // usually to be handled as IEnumerable through LINQ. + var genericType = ValueTypeBridge.GetStandard(GetValueSubType()); + Type[] typeArgs = { genericType }; + var containerType = typeof(System.Collections.Generic.List<>); + var retType = containerType.MakeGenericType(typeArgs); + object ret = Activator.CreateInstance(retType); + + var addMeth = retType.GetMethod("Add"); + + if (addMeth == null) + { + throw new InvalidOperationException("Failed to get Add() method of container to wrap value"); + } + + for (int i = 0; i < Count(); i++) + { + object[] args = new object[]{ this[i] }; + addMeth.Invoke(ret, args); + } + + return ret; + } + default: + throw new InvalidOperationException($"Unsupported value type to unwrap: {GetValueType()}"); + } + } + // Efl.Object conversions are made explicit to avoid ambiguity between // Set(Efl.Object) and Set(Value) when dealing with classes derived from // Efl.Object. @@ -1828,7 +2111,7 @@ public class Value : IDisposable, IComparable, IEquatable if (!GetValueType().IsString()) { throw (new ArgumentException( - "Trying to set non-string value on a string Eina.Value")); + "Trying to set string value on a non-string Eina.Value")); } // No need to worry about ownership as eina_value_set will copy the passed string. diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs index 03edea018c..c2ee5e2a31 100644 --- a/src/bindings/mono/eo_mono/EoWrapper.cs +++ b/src/bindings/mono/eo_mono/EoWrapper.cs @@ -67,15 +67,14 @@ public abstract class EoWrapper : IWrapper, IDisposable /// Internal usage: Constructor to actually call the native library constructors. C# subclasses /// must use the public constructor only. /// The pointer to the base native Eo class. - /// The managed type of the public constructor that originated this call. /// The Efl.Object parent of this instance. /// Name of the file from where the constructor is called. /// Number of the line from where the constructor is called. - protected EoWrapper(IntPtr baseKlass, System.Type managedType, Efl.Object parent, + protected EoWrapper(IntPtr baseKlass, Efl.Object parent, [CallerFilePath] string file = null, [CallerLineNumber] int line = 0) { - generated = ((object)this).GetType() == managedType; + generated = Efl.Eo.BindingEntity.IsBindingEntity(((object)this).GetType()); IntPtr actual_klass = baseKlass; if (!generated) { diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index 833ae78302..09c82a7e81 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -775,6 +775,22 @@ public class PrivateNativeClass : NativeClass } } +[System.AttributeUsage(System.AttributeTargets.Class | + System.AttributeTargets.Interface | + System.AttributeTargets.Enum | + System.AttributeTargets.Delegate | + System.AttributeTargets.Struct, + AllowMultiple = false, + Inherited = false) +] +public class BindingEntity: System.Attribute +{ + public static bool IsBindingEntity(System.Type t) + { + return Attribute.GetCustomAttribute(t, typeof(BindingEntity), false) != null; + } +} + public interface IWrapper { /// Pointer to internal Eo instance. diff --git a/src/examples/edje.mk b/src/examples/edje.mk index ce4f7afafd..c9f89b193b 100644 --- a/src/examples/edje.mk +++ b/src/examples/edje.mk @@ -48,7 +48,8 @@ edje/swallow.edc \ edje/table.edc \ edje/text.edc \ edje/textblock-hyphen.edc \ -edje/toggle_using_filter.edc +edje/toggle_using_filter.edc \ +edje/center_zoom.edc MULTISENSE_EDCS = edje/multisense.edc if ENABLE_MULTISENSE diff --git a/src/examples/edje/center_zoom.edc b/src/examples/edje/center_zoom.edc new file mode 100644 index 0000000000..21d07257a8 --- /dev/null +++ b/src/examples/edje/center_zoom.edc @@ -0,0 +1,105 @@ +collections { +group { name: "center_zoom_example"; + min: 360 360; + max: 360 360; + parts { + part { + name: "bg"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 0 255; + } + } + part { + name: "center_part"; + type: RECT; + description { + state: "default" 0.0; + min: 25 25; + max: 25 25; + rel1.to:"bg"; + rel2 { + relative: 1.0 0.5; + to: "bg"; + } + } + } + part { + name: "rectangle"; + type: RECT; + description { + state: "default" 0.0; + color: 0 0 255 128; + max: 150 150; + rel1 { + to: "bg"; + } + rel2 { + to: "bg"; + } + map { + on: 1; + zoom { + center: "center_part"; + x: 0.0; + y: 0.0; + } + } + } + description { + state: "zoom" 0.0; + inherit: "default" 0.0; + map { + on: 1; + zoom { + center: "center_part"; + x: 1; + y: 1; + } + } + } + } + part { + name: "title"; + type: TEXT; + description { + state: "default" 0.0; + color: 200 200 200 255; + align: 0.5 0.0; + rel1.to:"bg"; + rel2 { + relative: 1.0 0.0; + to: "bg"; + } + text { + text: "Center Zoom Example"; + font: "Sans"; + size: 16; + min: 1 1; + } + } + } + part { + name: "event"; + type: RECT; + mouse_events: 1; + description { + state: "default" 0.0; + color: 0 0 0 0; + } + } + } + programs { + program { + name: "move,bottom"; + signal: "mouse,up,1"; + source: "event"; + action: STATE_SET "zoom" 0.0; + transition: LINEAR 1.0; + target: "rectangle"; + } + } + } +} + diff --git a/src/examples/edje/meson.build b/src/examples/edje/meson.build index 21910ad389..ff57a6e29e 100644 --- a/src/examples/edje/meson.build +++ b/src/examples/edje/meson.build @@ -44,6 +44,7 @@ edc_files = [ 'textblock-hyphen.edc', 'toggle_using_filter.edc', 'multisense.edc', + 'center_zoom.edc', ] if (get_option('physics')) diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c index 3e12ab5218..672b7c4072 100644 --- a/src/lib/ecore_evas/ecore_evas.c +++ b/src/lib/ecore_evas/ecore_evas.c @@ -77,6 +77,8 @@ static void _ecore_evas_animator_freeze(Ecore_Animator *animator); static void _ecore_evas_animator_thaw(Ecore_Animator *animator); static void *_ecore_evas_animator_del(Ecore_Animator *animator); +static void _ecore_evas_event_del(void *data, const Efl_Event *ev EINA_UNUSED); + static void _ecore_evas_focus_out_dispatch(Ecore_Evas *ee, Efl_Input_Device *seat) { @@ -3432,6 +3434,12 @@ _ecore_evas_free(Ecore_Evas *ee) Efl_Input_Device *dev; Ecore_Evas_Interface *iface; + if (ee->self_del) + { + efl_event_callback_del(ee->evas, EFL_EVENT_INVALIDATE, _ecore_evas_event_del, ee); + ee->self_del = EINA_FALSE; + } + ee->deleted = EINA_TRUE; if (ee->refcount > 0) return; @@ -3494,7 +3502,7 @@ _ecore_evas_free(Ecore_Evas *ee) ee->prop.wm_rot.manual_mode.timer = NULL; eina_hash_free(ee->prop.cursors); ee->prop.cursors = NULL; - evas_free(ee->evas); + if (!ee->evas_dying) evas_free(ee->evas); ee->evas = NULL; ECORE_MAGIC_SET(ee, ECORE_MAGIC_NONE); ee->driver = NULL; @@ -5264,6 +5272,15 @@ ecore_evas_evas_new(Ecore_Evas *ee, int w, int h) return e; } +static void +_ecore_evas_event_del(void *data, const Efl_Event *ev EINA_UNUSED) +{ + Ecore_Evas *ee = data; + + ee->evas_dying = EINA_TRUE; + ecore_evas_free(ee); +} + EAPI void ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window) { @@ -5277,6 +5294,9 @@ ecore_evas_done(Ecore_Evas *ee, Eina_Bool single_window) if (single_window) evas_event_feed_mouse_in(ee->evas, (unsigned int)((unsigned long long)(ecore_time_get() * 1000.0) & 0xffffffff), NULL); + + efl_event_callback_add(ee->evas, EFL_EVENT_INVALIDATE, _ecore_evas_event_del, ee); + ee->self_del = EINA_TRUE; } static Ecore_Animator * diff --git a/src/lib/ecore_evas/ecore_evas_private.h b/src/lib/ecore_evas/ecore_evas_private.h index cfbb367e2b..e8db23b99e 100644 --- a/src/lib/ecore_evas/ecore_evas_private.h +++ b/src/lib/ecore_evas/ecore_evas_private.h @@ -385,6 +385,8 @@ struct _Ecore_Evas unsigned char animator_ticked : 1; unsigned char animator_ran : 1; unsigned char first_frame : 1; + unsigned char self_del : 1; + unsigned char evas_dying : 1; }; struct _Ecore_Evas_Aux_Hint diff --git a/src/lib/edje/edje_calc.c b/src/lib/edje/edje_calc.c index 7d948e29b1..dc2cb03af6 100644 --- a/src/lib/edje/edje_calc.c +++ b/src/lib/edje/edje_calc.c @@ -8,8 +8,11 @@ static void _edje_part_make_rtl(Edje_Part_Description_C static Edje_Part_Description_Common *_edje_get_description_by_orientation(Edje *ed, Edje_Part_Description_Common *src, Edje_Part_Description_Common **dst, unsigned char type); static void _edje_part_recalc_single(Edje *ed, Edje_Real_Part *ep, - Edje_Part_Description_Common *desc, Edje_Part_Description_Common *chosen_desc, - Edje_Real_Part *center, Edje_Real_Part *light, Edje_Real_Part *persp, + Edje_Part_Description_Common *desc, + Edje_Part_Description_Common *chosen_desc, + Edje_Real_Part *center, + Edje_Real_Part *zoom_center, + Edje_Real_Part *light, Edje_Real_Part *persp, Edje_Real_Part *rel1_to_x, Edje_Real_Part *rel1_to_y, Edje_Real_Part *rel2_to_x, Edje_Real_Part *rel2_to_y, Edje_Real_Part *clip_to, @@ -2279,6 +2282,7 @@ static void _edje_part_recalc_single_map(Edje *ed, Edje_Real_Part *ep EINA_UNUSED, Edje_Real_Part *center, + Edje_Real_Part *zoom_center, Edje_Real_Part *light, Edje_Real_Part *persp, Edje_Part_Description_Common *desc, @@ -2293,6 +2297,7 @@ _edje_part_recalc_single_map(Edje *ed, EINA_COW_CALC_MAP_BEGIN(params, params_write) { + //rotation center if (center) { params_write->center.x = ed->x + center->x + (center->w / 2); @@ -2304,6 +2309,17 @@ _edje_part_recalc_single_map(Edje *ed, params_write->center.y = ed->y + params->final.y + (params->final.h / 2); } params_write->center.z = 0; + //zoom center + if (zoom_center) + { + params_write->zoom_center.x = ed->x + zoom_center->x + (zoom_center->w / 2); + params_write->zoom_center.y = ed->y + zoom_center->y + (zoom_center->h / 2); + } + else + { + params_write->zoom_center.x = ed->x + params->final.x + (params->final.w / 2); + params_write->zoom_center.y = ed->y + params->final.y + (params->final.h / 2); + } params_write->rotation.x = desc->map.rot.x; params_write->rotation.y = desc->map.rot.y; @@ -2680,6 +2696,7 @@ _edje_part_recalc_single(Edje *ed, Edje_Part_Description_Common *desc, Edje_Part_Description_Common *chosen_desc, Edje_Real_Part *center, + Edje_Real_Part *zoom_center, Edje_Real_Part *light, Edje_Real_Part *persp, Edje_Real_Part *rel1_to_x, @@ -3056,7 +3073,7 @@ _edje_part_recalc_single(Edje *ed, EINA_COW_CALC_PHYSICS_END(params, params_write); } #endif - _edje_part_recalc_single_map(ed, ep, center, light, persp, desc, chosen_desc, params); + _edje_part_recalc_single_map(ed, ep, center, zoom_center, light, persp, desc, chosen_desc, params); } static void @@ -3757,7 +3774,7 @@ _edje_map_prop_set(Evas_Map *map, const Edje_Calc_Params *pf, //zoom evas_map_util_zoom(map, pf->ext->map->zoom.x, pf->ext->map->zoom.y, - pf->ext->map->center.x, pf->ext->map->center.y); + pf->ext->map->zoom_center.x, pf->ext->map->zoom_center.y); //rotate evas_map_util_3d_rotate(map, @@ -3994,6 +4011,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta int statep2 = -1; int statecl = -1; Edje_Real_Part *center[2] = { NULL, NULL }; + Edje_Real_Part *zoom_center[2] = { NULL, NULL }; Edje_Real_Part *light[2] = { NULL, NULL }; Edje_Real_Part *persp[2] = { NULL, NULL }; Edje_Real_Part *rp1[4] = { NULL, NULL, NULL, NULL }; @@ -4313,6 +4331,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta if (ep->param1.description->map.on) { center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.rot.id_center, &statec1); + zoom_center[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.zoom.id_center, &statec1); light[0] = _edje_real_part_state_get(ed, ep, flags, ep->param1.description->map.id_light, &statel1); if (chosen_desc->map.persp_on) @@ -4324,6 +4343,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta if (ep->param2 && ep->param2->description->map.on) { center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.rot.id_center, &statec2); + zoom_center[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.zoom.id_center, &statec2); light[1] = _edje_real_part_state_get(ed, ep, flags, ep->param2->description->map.id_light, &statel2); if (chosen_desc->map.persp_on) @@ -4359,7 +4379,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta #endif { _edje_part_recalc_single(ed, ep, ep->param1.description, - chosen_desc, center[0], light[0], + chosen_desc, center[0], zoom_center[0], light[0], persp[0], rp1[Rel1X], rp1[Rel1Y], rp1[Rel2X], rp1[Rel2Y], clip1, confine_to, threshold, p1, mmw, mmh, @@ -4405,7 +4425,7 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta #endif { _edje_part_recalc_single(ed, ep, ep->param2->description, - chosen_desc, center[1], light[1], + chosen_desc, center[1], zoom_center[1], light[1], persp[1], rp2[Rel1X], rp2[Rel1Y], rp2[Rel2X], rp2[Rel2Y], clip2, confine_to, threshold, p2, mmw, mmh, @@ -4690,6 +4710,8 @@ _edje_part_recalc(Edje *ed, Edje_Real_Part *ep, int flags, Edje_Calc_Params *sta p3_write->center.x = INTP(p1->ext->map->center.x, p2->ext->map->center.x, pos); p3_write->center.y = INTP(p1->ext->map->center.y, p2->ext->map->center.y, pos); p3_write->center.z = INTP(p1->ext->map->center.z, p2->ext->map->center.z, pos); + p3_write->zoom_center.x = INTP(p1->ext->map->zoom_center.x, p2->ext->map->zoom_center.x, pos); + p3_write->zoom_center.y = INTP(p1->ext->map->zoom_center.y, p2->ext->map->zoom_center.y, pos); p3_write->rotation.x = FFP(p1->ext->map->rotation.x, p2->ext->map->rotation.x, pos); p3_write->rotation.y = FFP(p1->ext->map->rotation.y, p2->ext->map->rotation.y, pos); p3_write->rotation.z = FFP(p1->ext->map->rotation.z, p2->ext->map->rotation.z, pos); diff --git a/src/lib/edje/edje_data.c b/src/lib/edje/edje_data.c index c273b4db02..2216c835e5 100644 --- a/src/lib/edje/edje_data.c +++ b/src/lib/edje/edje_data.c @@ -798,6 +798,7 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.id_persp", map.id_persp, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.id_light", map.id_light, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.id_center", map.rot.id_center, EET_T_INT); \ + EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.zoom.id_center", map.zoom.id_center, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.x", map.rot.x, EDJE_T_FLOAT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.y", map.rot.y, EDJE_T_FLOAT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.z", map.rot.z, EDJE_T_FLOAT); \ @@ -892,6 +893,7 @@ _edje_edd_init(void) EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.id_persp", Dec.map.id_persp, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.id_light", Dec.map.id_light, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.id_center", Dec.map.rot.id_center, EET_T_INT); \ + EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.zoom.id_center", Dec.map.zoom.id_center, EET_T_INT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.x", Dec.map.rot.x, EDJE_T_FLOAT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.y", Dec.map.rot.y, EDJE_T_FLOAT); \ EET_DATA_DESCRIPTOR_ADD_BASIC(Edd, Type, "map.rot.z", Dec.map.rot.z, EDJE_T_FLOAT); \ diff --git a/src/lib/edje/edje_main.c b/src/lib/edje/edje_main.c index dc2c35cba5..d794c961b4 100644 --- a/src/lib/edje/edje_main.c +++ b/src/lib/edje/edje_main.c @@ -16,7 +16,7 @@ Eina_Cow *_edje_calc_params_physics_cow = NULL; Edje_Global *_edje_global_obj = NULL; static const Edje_Calc_Params_Map default_calc_map = { - { 0, 0, 0 }, { 0.0, 0.0, 0.0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0.0, 0.0 }, NULL, 0 + { 0, 0, 0 }, { 0, 0 }, { 0.0, 0.0, 0.0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0.0, 0.0 }, NULL, 0 }; static const Edje_Calc_Params_Physics default_calc_physics = { diff --git a/src/lib/edje/edje_private.h b/src/lib/edje/edje_private.h index 502cd44bdb..fd8322bbd5 100644 --- a/src/lib/edje/edje_private.h +++ b/src/lib/edje/edje_private.h @@ -1310,6 +1310,7 @@ struct _Edje_Part_Description_Common } rot; struct { FLOAT_T x, y; + int id_center; } zoom; Edje_Map_Color **colors; /* List of the Edje_Map_Color */ unsigned int colors_count; @@ -1812,6 +1813,9 @@ struct _Edje_Calc_Params_Map struct { int x, y, z; } center; // 12 + struct { + int x, y; + } zoom_center; // 12 struct { FLOAT_T x, y, z; } rotation; // 24 diff --git a/src/lib/efl/interfaces/efl_gfx_image.eo b/src/lib/efl/interfaces/efl_gfx_image.eo index 1ef54efe8c..64bd6b873d 100644 --- a/src/lib/efl/interfaces/efl_gfx_image.eo +++ b/src/lib/efl/interfaces/efl_gfx_image.eo @@ -40,6 +40,17 @@ enum @beta Efl.Gfx.Image_Scale_Type none [[Not scale the image]] } +struct Efl.Gfx.Image.Stretch_Region +{ + [[This struct holds the description of a stretchable region in one dimension (vertical or horizontal). + Used when scaling an image. + + $offset + $length should be smaller than image size in that dimension. + ]] + offset: uint; [[First pixel of the stretchable region, starting at 0.]] + length: uint; [[Length of the stretchable region in pixels.]] +} + interface @beta Efl.Gfx.Image { [[Common APIs for all 2D images that can be rendered on the canvas.]] @@ -76,6 +87,22 @@ interface @beta Efl.Gfx.Image ratio: double; [[The image's ratio.]] } } + @property content_region { + [[Return the relative area enclosed inside the image where content is expected. + + We do expect content to be inside the limit defined by the border or inside the + stretch region. If a stretch region is provided, the content region will encompass the + non strechable area that are surrounded by stretchable area. If no border and no + stretch region is set, they are assumed to be zero and the full object geometry is + where content can be layout on top. The area size change with the object size. + + The geometry of the area is expressed relative to the geometry of the object. + ]] + get { } + values { + region: Eina.Rect; [[A rectangle inside the object boundary that where content is expected.]] + } + } @property border { [[Dimensions of this image's border, a region that does not scale with the center area. @@ -140,6 +167,26 @@ interface @beta Efl.Gfx.Image fill: Efl.Gfx.Border_Fill_Mode; [[Fill mode of the center region.]] } } + @property stretch_region { + [[This property defines the stretchable pixels region of an image. + + When the regions are set by the user, the method will walk the iterators + once and then destroy them. When the regions are retrieved by the user, + it is his responsibility to destroy the iterators.. It will remember the + information for the lifetime of the object. It will ignore all value + of @.border, @.border_scale and @.border_center_fill . To reset the object + you can just pass $null to both horizontal and vertical at the same + time. + ]] + set { + return: Eina.Error; [[return an error code if the stretch_region provided are incorrect.]] + } + get {} + values { + horizontal: iterator; [[Representation of area that are stretchable in the image horizontal space.]] + vertical: iterator; [[Representation of area that are stretchable in the image vertical space.]] + } + } @property image_size { [[This represents the size of the original image in pixels. diff --git a/src/lib/efl/interfaces/efl_gfx_image_orientable.eo b/src/lib/efl/interfaces/efl_gfx_image_orientable.eo index 2070feb737..5a3003094b 100644 --- a/src/lib/efl/interfaces/efl_gfx_image_orientable.eo +++ b/src/lib/efl/interfaces/efl_gfx_image_orientable.eo @@ -1,6 +1,6 @@ parse efl_ui_layout_orientable; -enum @beta Efl.Gfx.Image_Orientation +enum Efl.Gfx.Image_Orientation { [[An orientation type, to rotate and flip images. @@ -25,12 +25,12 @@ enum @beta Efl.Gfx.Image_Orientation flip_bitmask = 12 [[Bitmask that can be used to isolate flipping values, that is, $flip_vertical and $flip_horizontal.]] } -interface @beta Efl.Gfx.Image_Orientable +interface Efl.Gfx.Image_Orientable { [[Interface for objects which can be oriented.]] - c_prefix: efl_gfx_image; + c_prefix: efl_gfx; methods { - @property orientation { + @property image_orientation { [[Control the orientation (rotation and flipping) of a visual object. This can be used to set the rotation on an image or a window, for diff --git a/src/lib/efl/interfaces/efl_input_device.eo b/src/lib/efl/interfaces/efl_input_device.eo index d296c5cafc..a015cf83f4 100644 --- a/src/lib/efl/interfaces/efl_input_device.eo +++ b/src/lib/efl/interfaces/efl_input_device.eo @@ -1,4 +1,4 @@ -enum @beta Efl.Input.Device_Type +enum Efl.Input.Device_Type { [[General type of input device. @@ -19,7 +19,7 @@ enum @beta Efl.Input.Device_Type @property canvas { values { canvas: Efl.Canvas; } } */ -class @beta Efl.Input.Device extends Efl.Object +class Efl.Input.Device extends Efl.Object { [[Represents a pointing device such as a touch finger, pen or mouse. ]] diff --git a/src/lib/efl/interfaces/efl_input_types.eot b/src/lib/efl/interfaces/efl_input_types.eot index 61f3ee922d..a716686528 100644 --- a/src/lib/efl/interfaces/efl_input_types.eot +++ b/src/lib/efl/interfaces/efl_input_types.eot @@ -1,4 +1,4 @@ -enum @beta Efl.Pointer.Action +enum Efl.Pointer.Action { [[Pointer event type. Represents which kind of event this is. @@ -18,7 +18,7 @@ enum @beta Efl.Pointer.Action axis, [[Axis event (pen, stick, ...).]] } -enum @beta Efl.Pointer.Flags +enum Efl.Pointer.Flags { [[Pointer flags indicating whether a double or triple click is under way. @@ -29,7 +29,7 @@ enum @beta Efl.Pointer.Flags triple_click = (1 << 1), [[This mouse button press was the 3rd press of a triple click]] } -enum @beta Efl.Input.Flags +enum Efl.Input.Flags { [[Special flags set during an input event propagation. @@ -74,7 +74,7 @@ enum @beta Efl.Input.Object_Pointer_Mode { ]] } -enum @beta Efl.Input.Value { +enum @beta Efl.Input.Value { [[Keys for the generic values of all events. @since 1.19 diff --git a/src/lib/efl/interfaces/efl_pack.eo b/src/lib/efl/interfaces/efl_pack.eo index 39f686e20c..7c65928677 100644 --- a/src/lib/efl/interfaces/efl_pack.eo +++ b/src/lib/efl/interfaces/efl_pack.eo @@ -1,4 +1,4 @@ -interface @beta Efl.Pack extends Efl.Container +interface Efl.Pack extends Efl.Container { [[Common interface for objects (containers) with multiple contents (sub-objects) which can be added and removed at runtime. diff --git a/src/lib/efl/interfaces/efl_pack_linear.eo b/src/lib/efl/interfaces/efl_pack_linear.eo index 79ea27c5d9..2ba9446fdc 100644 --- a/src/lib/efl/interfaces/efl_pack_linear.eo +++ b/src/lib/efl/interfaces/efl_pack_linear.eo @@ -1,4 +1,4 @@ -interface @beta Efl.Pack_Linear extends Efl.Pack +interface Efl.Pack_Linear extends Efl.Pack { [[Common interface for objects (containers) with multiple contents (sub-objects) which can be added and removed at runtime in a linear fashion. diff --git a/src/lib/efl/interfaces/efl_ui_autorepeat.eo b/src/lib/efl/interfaces/efl_ui_autorepeat.eo index 92dcc3a88a..e1651df093 100644 --- a/src/lib/efl/interfaces/efl_ui_autorepeat.eo +++ b/src/lib/efl/interfaces/efl_ui_autorepeat.eo @@ -1,4 +1,4 @@ -interface @beta Efl.Ui.Autorepeat { +interface Efl.Ui.Autorepeat { [[Interface for autorepeating clicks. This interface abstracts functions for enabling / disabling this feature. diff --git a/src/lib/efl/interfaces/efl_ui_layout_orientable.eo b/src/lib/efl/interfaces/efl_ui_layout_orientable.eo index 98142646e9..34da902e56 100644 --- a/src/lib/efl/interfaces/efl_ui_layout_orientable.eo +++ b/src/lib/efl/interfaces/efl_ui_layout_orientable.eo @@ -1,6 +1,6 @@ parse efl_gfx_image_orientable; -enum @beta Efl.Ui.Layout_Orientation +enum Efl.Ui.Layout_Orientation { [[Orientation for UI objects and layouts that can have multiple configurations. @@ -24,10 +24,10 @@ enum @beta Efl.Ui.Layout_Orientation along the selected axis.]] } -interface @beta Efl.Ui.Layout_Orientable +interface Efl.Ui.Layout_Orientable { [[Interface for UI objects which can have more than one orientation. - + For example, sliders, which can be horizontal or vertical, or container boxes, which can arrange their elements in a horizontal or vertical fashion. ]] diff --git a/src/lib/elementary/efl_ui_box.eo b/src/lib/elementary/efl_ui_box.eo index 4b27389c52..008fb6d46c 100644 --- a/src/lib/elementary/efl_ui_box.eo +++ b/src/lib/elementary/efl_ui_box.eo @@ -1,4 +1,4 @@ -class @beta Efl.Ui.Box extends Efl.Ui.Widget implements Efl.Pack_Linear, Efl.Pack_Layout, +class Efl.Ui.Box extends Efl.Ui.Widget implements Efl.Pack_Linear, Efl.Pack_Layout, Efl.Ui.Layout_Orientable, Efl.Gfx.Arrangement { [[A container that arranges children widgets in a vertical or horizontal fashion. diff --git a/src/lib/elementary/efl_ui_button.eo b/src/lib/elementary/efl_ui_button.eo index 7bf7f17f04..449d501276 100644 --- a/src/lib/elementary/efl_ui_button.eo +++ b/src/lib/elementary/efl_ui_button.eo @@ -1,4 +1,4 @@ -class @beta Efl.Ui.Button extends Efl.Ui.Layout_Base implements Efl.Ui.Clickable, Efl.Ui.Autorepeat, +class Efl.Ui.Button extends Efl.Ui.Layout_Base implements Efl.Ui.Clickable, Efl.Ui.Autorepeat, Efl.Text, Efl.Content, Efl.Access.Widget.Action { diff --git a/src/lib/elementary/efl_ui_clickable.eo b/src/lib/elementary/efl_ui_clickable.eo index de3a3e4fb1..ace6f6d6e7 100644 --- a/src/lib/elementary/efl_ui_clickable.eo +++ b/src/lib/elementary/efl_ui_clickable.eo @@ -1,4 +1,4 @@ -struct Efl.Ui.Clickable_Clicked { +struct @beta Efl.Ui.Clickable_Clicked { [[A struct that expresses a click in elementary.]] repeated : int; [[The amount of how often the clicked event was repeated in a certain amount of time]] button : int; [[The Button that is pressed]] diff --git a/src/lib/elementary/efl_ui_grid.c b/src/lib/elementary/efl_ui_grid.c index d27899d907..20ef53d2f1 100644 --- a/src/lib/elementary/efl_ui_grid.c +++ b/src/lib/elementary/efl_ui_grid.c @@ -746,12 +746,7 @@ _grid_item_process(Eo *obj, Efl_Ui_Grid_Data *pd, EINA_UNUSED Efl_Ui_Grid_Item * if (!efl_ui_widget_sub_object_add(obj, it)) return EINA_FALSE; - //FIXME: This is tricky workaround for set select mode and parent value. - EFL_UI_GRID_ITEM_DATA_GET_OR_RETURN(it, gd, EINA_FALSE); - EFL_UI_ITEM_DATA_GET_OR_RETURN(it, id, EINA_FALSE); - id->select_mode = &(pd->select_mode); - id->parent = obj; - gd->parent = obj; + efl_ui_item_container_set(it, obj); efl_canvas_group_member_add(pd->pan, it); efl_ui_mirrored_set(it, efl_ui_mirrored_get(obj)); @@ -769,11 +764,7 @@ static void _grid_item_unpack_internal(Eo *obj, Efl_Ui_Grid_Data *pd, Efl_Ui_Grid_Item *it) { EFL_UI_GRID_ITEM_CHECK_OR_RETURN(it); - EFL_UI_GRID_ITEM_DATA_GET_OR_RETURN(it, gd); - EFL_UI_ITEM_DATA_GET_OR_RETURN(it, id); - id->select_mode = NULL; - id->parent = NULL; - gd->parent = NULL; + efl_ui_item_container_set(it, NULL); pd->items = eina_list_remove(pd->items, it); if (efl_ui_item_selected_get(it)) diff --git a/src/lib/elementary/efl_ui_grid_item_private.h b/src/lib/elementary/efl_ui_grid_item_private.h index cec53f91ce..d8c4009826 100644 --- a/src/lib/elementary/efl_ui_grid_item_private.h +++ b/src/lib/elementary/efl_ui_grid_item_private.h @@ -7,7 +7,6 @@ typedef struct _Efl_Ui_Grid_Item_Data { // Eo Objects Eo *obj; /* Self-Object */ - Eo *parent; /* Parent Widget */ Eina_Rect geo; int index; struct { diff --git a/src/lib/elementary/efl_ui_image.c b/src/lib/elementary/efl_ui_image.c index 8f23228e7d..02dd574378 100644 --- a/src/lib/elementary/efl_ui_image.c +++ b/src/lib/elementary/efl_ui_image.c @@ -1362,7 +1362,7 @@ _efl_ui_image_efl_gfx_image_load_controller_load_size_get(const Eo *obj EINA_UNU } EOLIAN static void -_efl_ui_image_efl_gfx_image_orientable_orientation_set(Eo *obj, Efl_Ui_Image_Data *sd, Efl_Gfx_Image_Orientation orient) +_efl_ui_image_efl_gfx_image_orientable_image_orientation_set(Eo *obj, Efl_Ui_Image_Data *sd, Efl_Gfx_Image_Orientation orient) { if (sd->edje) return; if (sd->orient == orient) return; @@ -1372,7 +1372,7 @@ _efl_ui_image_efl_gfx_image_orientable_orientation_set(Eo *obj, Efl_Ui_Image_Dat } EOLIAN static Efl_Gfx_Image_Orientation -_efl_ui_image_efl_gfx_image_orientable_orientation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd) +_efl_ui_image_efl_gfx_image_orientable_image_orientation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd) { return sd->orient; } diff --git a/src/lib/elementary/efl_ui_image.eo b/src/lib/elementary/efl_ui_image.eo index 521e99743b..d6db562358 100644 --- a/src/lib/elementary/efl_ui_image.eo +++ b/src/lib/elementary/efl_ui_image.eo @@ -100,7 +100,7 @@ class @beta Efl.Ui.Image extends Efl.Ui.Widget implements Efl.Ui.Clickable, Efl. Efl.Gfx.Image_Load_Controller.load_size { get; set; } Efl.Gfx.Image.smooth_scale { get; set; } Efl.Gfx.Image.scale_type { get; set; } - Efl.Gfx.Image_Orientable.orientation { get; set; } + Efl.Gfx.Image_Orientable.image_orientation { get; set; } Efl.Player.playable { get; } Efl.Player.play { get; set; } Efl.Layout.Signal.signal_emit; diff --git a/src/lib/elementary/efl_ui_image_zoomable.c b/src/lib/elementary/efl_ui_image_zoomable.c index 68e6e4dafd..9d834afad2 100644 --- a/src/lib/elementary/efl_ui_image_zoomable.c +++ b/src/lib/elementary/efl_ui_image_zoomable.c @@ -1331,7 +1331,7 @@ _orient_apply(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd) } EOLIAN static void -_efl_ui_image_zoomable_efl_gfx_image_orientable_orientation_set(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd, +_efl_ui_image_zoomable_efl_gfx_image_orientable_image_orientation_set(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd, Efl_Gfx_Image_Orientation orient) { if (sd->orient == orient) return; @@ -1341,7 +1341,7 @@ _efl_ui_image_zoomable_efl_gfx_image_orientable_orientation_set(Eo *obj, Efl_Ui_ } EOLIAN static Efl_Gfx_Image_Orientation -_efl_ui_image_zoomable_efl_gfx_image_orientable_orientation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Image_Zoomable_Data *sd) +_efl_ui_image_zoomable_efl_gfx_image_orientable_image_orientation_get(const Eo *obj EINA_UNUSED, Efl_Ui_Image_Zoomable_Data *sd) { return sd->orient; } diff --git a/src/lib/elementary/efl_ui_image_zoomable.eo b/src/lib/elementary/efl_ui_image_zoomable.eo index 85c553e0b0..6b4dccdaa4 100644 --- a/src/lib/elementary/efl_ui_image_zoomable.eo +++ b/src/lib/elementary/efl_ui_image_zoomable.eo @@ -65,7 +65,7 @@ class @beta Efl.Ui.Image_Zoomable extends Efl.Ui.Image implements Efl.Ui.Zoom, Efl.Access.Widget.Action.elm_actions { get; } Efl.File.load; Efl.File.file { get; set; } - Efl.Gfx.Image_Orientable.orientation { get; set; } + Efl.Gfx.Image_Orientable.image_orientation { get; set; } Efl.Layout.Group.group_size_min { get; } Efl.Layout.Group.group_size_max { get; } Efl.Layout.Signal.signal_callback_add; diff --git a/src/lib/elementary/efl_ui_item.c b/src/lib/elementary/efl_ui_item.c index 3f87832db5..8b16afd5f2 100644 --- a/src/lib/elementary/efl_ui_item.c +++ b/src/lib/elementary/efl_ui_item.c @@ -143,10 +143,12 @@ _efl_ui_item_part_content_efl_content_content_unset(Eo *obj, void *pd EINA_UNUSE static void _item_select(Eo *obj, Efl_Ui_Item_Data *pd) { - if (pd->selected && - (*(pd->select_mode) != EFL_UI_SELECT_MODE_SINGLE_ALWAYS)) + Efl_Ui_Select_Mode m; + if (!pd->parent) + return; + m = efl_ui_select_mode_get(pd->parent); + if (m == EFL_UI_SELECT_MODE_NONE || (pd->selected && m != EFL_UI_SELECT_MODE_SINGLE_ALWAYS)) return; - if (*(pd->select_mode) == EFL_UI_SELECT_MODE_NONE) return; ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd); @@ -206,6 +208,10 @@ _item_mouse_up(void *data, { Evas_Event_Mouse_Up *ev = event_info; Eo *item = data; + Efl_Ui_Select_Mode m; + + if (!efl_ui_item_container_get(item)) + return; EFL_UI_ITEM_DATA_GET_OR_RETURN(item, pd); ELM_WIDGET_DATA_GET_OR_RETURN(item, wd); if (wd->disabled) return; @@ -226,9 +232,10 @@ _item_mouse_up(void *data, edje_object_signal_emit(wd->resize_obj, "efl,state,unpressed", "efl"); efl_event_callback_call(item, EFL_UI_EVENT_UNPRESSED, NULL); - if ((*(pd->select_mode) != EFL_UI_SELECT_MODE_SINGLE_ALWAYS) && (pd->selected)) + m = efl_ui_select_mode_get(efl_ui_item_container_get(item)); + if ((m != EFL_UI_SELECT_MODE_SINGLE_ALWAYS) && (pd->selected)) _item_unselect(item, pd); - else if (*(pd->select_mode) != EFL_UI_SELECT_MODE_NONE) + else if (m != EFL_UI_SELECT_MODE_NONE) _item_select(item, pd); } @@ -380,6 +387,19 @@ _efl_ui_item_selected_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd) return pd->selected; } +EOLIAN static void +_efl_ui_item_container_set(Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd, Efl_Ui_Widget *container) +{ + pd->parent = container; +} + +EOLIAN static Efl_Ui_Widget* +_efl_ui_item_container_get(const Eo *obj EINA_UNUSED, Efl_Ui_Item_Data *pd) +{ + return pd->parent; +} + + /* Internal EO APIs and hidden overrides */ #define EFL_UI_ITEM_EXTRA_OPS \ diff --git a/src/lib/elementary/efl_ui_item.eo b/src/lib/elementary/efl_ui_item.eo index 50e1e1c739..9ece7e4c0c 100644 --- a/src/lib/elementary/efl_ui_item.eo +++ b/src/lib/elementary/efl_ui_item.eo @@ -18,6 +18,15 @@ abstract @beta Efl.Ui.Item extends Efl.Ui.Layout_Base implements Efl.Ui.Selectab select: bool; } } + @property container { + [[The container this object is part of. + + You should never use this property yourself, the container will set it. Unsetting this while the item is packed into a container does not have an impact on its state in the container. + ]] + values { + container : Efl.Ui.Widget; [[The container this item is in.]] + } + } } implements { //Efl.Object diff --git a/src/lib/elementary/efl_ui_item_private.h b/src/lib/elementary/efl_ui_item_private.h index b8849a2316..ea8ac073c9 100644 --- a/src/lib/elementary/efl_ui_item_private.h +++ b/src/lib/elementary/efl_ui_item_private.h @@ -9,7 +9,6 @@ typedef struct _Efl_Ui_Item_Data Eo *obj; /* Self-Object */ Eo *parent; /* Parent Widget */ - Efl_Ui_Select_Mode *select_mode; /* Select Mdoe of parent widget */ Ecore_Timer *longpress_timer; /* Timer for longpress handle */ // Boolean Data diff --git a/src/lib/elementary/efl_ui_list.c b/src/lib/elementary/efl_ui_list.c index 7e10f06618..524c96993d 100644 --- a/src/lib/elementary/efl_ui_list.c +++ b/src/lib/elementary/efl_ui_list.c @@ -667,16 +667,11 @@ _list_item_unselected(void *data, const Efl_Event *event) } static Eina_Bool -_list_item_process(Eo *obj, Efl_Ui_List_Data *pd, EINA_UNUSED Efl_Ui_List_Item *it) +_list_item_process(Eo *obj, Efl_Ui_List_Data *pd EINA_UNUSED, Efl_Ui_List_Item *it) { EFL_UI_LIST_ITEM_CHECK_OR_RETURN(it, EINA_FALSE); - //FIXME: This is tricky workaround for set select mode and parent value. - EFL_UI_LIST_ITEM_DATA_GET_OR_RETURN(it, ld, EINA_FALSE); - EFL_UI_ITEM_DATA_GET_OR_RETURN(it, id, EINA_FALSE); - id->select_mode = &(pd->select_mode); - id->parent = obj; - ld->parent = obj; + efl_ui_item_container_set(it, obj); efl_ui_mirrored_set(it, efl_ui_mirrored_get(obj)); efl_event_callback_add(it, EFL_UI_EVENT_PRESSED, _list_item_pressed, obj); @@ -692,11 +687,7 @@ static void _list_item_clear(Eo *obj, Efl_Ui_List_Data *pd EINA_UNUSED, EINA_UNUSED Efl_Ui_List_Item *it) { EFL_UI_LIST_ITEM_CHECK_OR_RETURN(it); - EFL_UI_LIST_ITEM_DATA_GET_OR_RETURN(it, ld); - EFL_UI_ITEM_DATA_GET_OR_RETURN(it, id); - id->select_mode = NULL; - id->parent = NULL; - ld->parent = NULL; + efl_ui_item_container_set(it, NULL); efl_event_callback_del(it, EFL_UI_EVENT_PRESSED, _list_item_pressed, obj); efl_event_callback_del(it, EFL_UI_EVENT_UNPRESSED, _list_item_unpressed, obj); diff --git a/src/lib/elementary/efl_ui_list_item_private.h b/src/lib/elementary/efl_ui_list_item_private.h index e68b3fa14a..0df36bc459 100644 --- a/src/lib/elementary/efl_ui_list_item_private.h +++ b/src/lib/elementary/efl_ui_list_item_private.h @@ -7,7 +7,6 @@ typedef struct _Efl_Ui_List_Item_Data { // Eo Objects Eo *obj; /* Self-Object */ - Eo *parent; /* Parent Widget */ Eina_Bool needs_size_calc : 1; /* Flag for Size calculation */ } Efl_Ui_List_Item_Data; diff --git a/src/lib/elementary/efl_ui_progressbar.c b/src/lib/elementary/efl_ui_progressbar.c index f085924893..19b49bfa2e 100644 --- a/src/lib/elementary/efl_ui_progressbar.c +++ b/src/lib/elementary/efl_ui_progressbar.c @@ -593,23 +593,24 @@ _progressbar_part_value_get(Efl_Ui_Progressbar_Data *sd, const char* part) EOLIAN static void _efl_ui_progressbar_efl_ui_range_display_range_value_set(Eo *obj, Efl_Ui_Progressbar_Data *sd, double val) { - if (val < sd->val_min) - { - ERR("Error, value is less than minimum"); - return; - } - - if (val > sd->val_max) - { - ERR("Error, value is greater than maximum"); - return; - } if (EINA_DBL_EQ(sd->val, val)) return; if (elm_widget_is_legacy(obj)) _progressbar_part_value_set(obj, sd, "elm.cur.progressbar", val); else - _progressbar_part_value_set(obj, sd, "efl.cur.progressbar", val); + { + if (val < sd->val_min) + { + ERR("Error, value is less than minimum"); + return; + } + if (val > sd->val_max) + { + ERR("Error, value is greater than maximum"); + return; + } + _progressbar_part_value_set(obj, sd, "efl.cur.progressbar", val); + } } EOLIAN static double @@ -1052,7 +1053,7 @@ elm_progressbar_unit_format_set(Evas_Object *obj, const char *units) EAPI const char * elm_progressbar_unit_format_get(const Evas_Object *obj) { - const char *fmt; + const char *fmt = NULL; efl_ui_format_string_get(obj, &fmt, NULL); return fmt; } diff --git a/src/lib/elementary/efl_ui_slider.c b/src/lib/elementary/efl_ui_slider.c index 3a6de63a26..2eb3f28ac7 100644 --- a/src/lib/elementary/efl_ui_slider.c +++ b/src/lib/elementary/efl_ui_slider.c @@ -748,16 +748,18 @@ _efl_ui_slider_efl_ui_range_display_range_limits_get(const Eo *obj EINA_UNUSED, EOLIAN static void _efl_ui_slider_efl_ui_range_display_range_value_set(Eo *obj, Efl_Ui_Slider_Data *sd, double val) { - if (val < sd->val_min) + if (!elm_widget_is_legacy(obj)) { - ERR("Error, value is less than minimum"); - return; - } - - if (val > sd->val_max) - { - ERR("Error, value is greater than maximum"); - return; + if (val < sd->val_min) + { + ERR("Error, value is less than minimum"); + return; + } + if (val > sd->val_max) + { + ERR("Error, value is greater than maximum"); + return; + } } if (EINA_DBL_EQ(val, sd->val)) return; diff --git a/src/lib/elementary/efl_ui_table.eo b/src/lib/elementary/efl_ui_table.eo index ec9a7552d9..6d66968250 100644 --- a/src/lib/elementary/efl_ui_table.eo +++ b/src/lib/elementary/efl_ui_table.eo @@ -1,8 +1,8 @@ -class @beta Efl.Ui.Table extends Efl.Ui.Widget implements Efl.Pack_Table, Efl.Pack_Layout, +class Efl.Ui.Table extends Efl.Ui.Widget implements Efl.Pack_Table, Efl.Pack_Layout, Efl.Ui.Layout_Orientable, Efl.Gfx.Arrangement { [[Widget container that arranges its elements in a grid. - + The amount of rows and columns can be controlled with @Efl.Pack_Table.table_rows and @Efl.Pack_Table.table_columns, and elements can be manually positioned with @Efl.Pack_Table.pack_table. diff --git a/src/lib/elementary/efl_ui_text.c b/src/lib/elementary/efl_ui_text.c index 87f2ca5cc2..34e8a4f62b 100644 --- a/src/lib/elementary/efl_ui_text.c +++ b/src/lib/elementary/efl_ui_text.c @@ -1427,7 +1427,6 @@ _long_press_cb(void *data, const Efl_Event *ev EINA_UNUSED) sd->long_pressed = EINA_TRUE; sd->longpress_timer = NULL; - efl_event_callback_call(data, EFL_UI_EVENT_LONGPRESSED, NULL); } static void diff --git a/src/lib/elementary/elm_code_widget.eo b/src/lib/elementary/elm_code_widget.eo index a9d561423d..bb24d1b9fb 100644 --- a/src/lib/elementary/elm_code_widget.eo +++ b/src/lib/elementary/elm_code_widget.eo @@ -15,7 +15,7 @@ enum @beta Elm.Code_Widget_Scroller_Policy struct @extern Elm.Code; [[Elementary code main data structure]] /* The main interface currently defined in code */ struct @extern Elm.Code_Line; [[Elementary code line data structure]] /* Parts of the interface currently defined in code */ -class @beta Elm.Code_Widget extends Efl.Ui.Layout_Base +class @beta Elm.Code_Widget extends Efl.Ui.Layout { [[Elementary code widget]] c_prefix: efl_ui_code_widget; diff --git a/src/lib/elementary/elm_slider.c b/src/lib/elementary/elm_slider.c index 8239e475ee..a603894be7 100644 --- a/src/lib/elementary/elm_slider.c +++ b/src/lib/elementary/elm_slider.c @@ -1124,7 +1124,7 @@ _indi_default_format_free_cb(void *data) } EOLIAN static void -_elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *_pd EINA_UNUSED, const char *template) +_elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *_pd EINA_UNUSED, const char *template, Efl_Ui_Format_String_Type type EINA_UNUSED) { Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); Elm_Slider_Data *sd = efl_data_scope_get(pd->obj, ELM_SLIDER_CLASS); @@ -1135,13 +1135,13 @@ _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *_pd EI efl_ui_format_func_set(efl_part(pd->obj, "indicator"), pd->obj, _indi_default_format_cb, _indi_default_format_free_cb); } -EOLIAN static const char * -_elm_slider_part_indicator_efl_ui_format_format_string_get(const Eo *obj, void *_pd EINA_UNUSED) +EOLIAN static void +_elm_slider_part_indicator_efl_ui_format_format_string_get(const Eo *obj, void *_pd EINA_UNUSED, const char **template, Efl_Ui_Format_String_Type *type EINA_UNUSED) { Elm_Part_Data *pd = efl_data_scope_get(obj, EFL_UI_WIDGET_PART_CLASS); Elm_Slider_Data *sd = efl_data_scope_get(pd->obj, ELM_SLIDER_CLASS); - return sd->indi_template; + if (template) *template = sd->indi_template; } EOLIAN static void @@ -1207,7 +1207,7 @@ elm_slider_unit_format_set(Evas_Object *obj, const char *units) EAPI const char * elm_slider_unit_format_get(const Evas_Object *obj) { - const char* fmt; + const char* fmt = NULL; efl_ui_format_string_get(obj, &fmt, NULL); return fmt; } @@ -1386,7 +1386,7 @@ elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator) EAPI const char * elm_slider_indicator_format_get(const Evas *obj) { - const char *fmt; + const char *fmt = NULL; efl_ui_format_string_get(efl_part(obj, "indicator"), &fmt, NULL); return fmt; } diff --git a/src/lib/elementary/elm_slider_part_indicator_eo.c b/src/lib/elementary/elm_slider_part_indicator_eo.c index 54882942b1..369285bc30 100644 --- a/src/lib/elementary/elm_slider_part_indicator_eo.c +++ b/src/lib/elementary/elm_slider_part_indicator_eo.c @@ -9,11 +9,9 @@ EOAPI EFL_FUNC_BODY_CONST(elm_slider_part_indicator_visible_mode_get, Elm_Slider void _elm_slider_part_indicator_efl_ui_format_format_cb_set(Eo *obj, void *pd, void *func_data, Efl_Ui_Format_Func func, Eina_Free_Cb func_free_cb); +void _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *_pd, const char *template, Efl_Ui_Format_String_Type type); -void _elm_slider_part_indicator_efl_ui_format_format_string_set(Eo *obj, void *pd, const char *units); - - -const char *_elm_slider_part_indicator_efl_ui_format_format_string_get(const Eo *obj, void *pd); +void _elm_slider_part_indicator_efl_ui_format_format_string_get (const Eo *obj, void *_pd, const char **template, Efl_Ui_Format_String_Type *type); void _elm_slider_part_indicator_efl_ui_format_apply_formatted_value(Eo *obj, Elm_Part_Data *pd); diff --git a/src/lib/eolian_cxx/grammar/attributes.hpp b/src/lib/eolian_cxx/grammar/attributes.hpp index d33fcf2de7..b3efcce5a8 100644 --- a/src/lib/eolian_cxx/grammar/attributes.hpp +++ b/src/lib/eolian_cxx/grammar/attributes.hpp @@ -9,7 +9,10 @@ namespace efl { namespace eolian { namespace grammar { namespace attributes { -struct unused_type {}; +struct unused_type { + unused_type() = default; + unused_type(std::nullptr_t) {} +}; unused_type const unused = {}; template diff --git a/src/lib/eolian_cxx/grammar/class_implementation.hpp b/src/lib/eolian_cxx/grammar/class_implementation.hpp index 615ee6022e..74283352e7 100644 --- a/src/lib/eolian_cxx/grammar/class_implementation.hpp +++ b/src/lib/eolian_cxx/grammar/class_implementation.hpp @@ -15,6 +15,7 @@ #include "grammar/type_impl.hpp" #include "grammar/attribute_reorder.hpp" #include "grammar/part_implementation.hpp" +#include "grammar/ignore_warning.hpp" namespace efl { namespace eolian { namespace grammar { @@ -42,6 +43,9 @@ struct class_implementation_generator .generate(sink, std::make_tuple(cls.namespaces, cls.cxx_name), add_lower_case_context(ctx))) return false; + if(!as_generator(ignore_warning_begin).generate(sink, nullptr, ctx)) + return false; + #ifndef USE_EOCXX_INHERIT_ONLY if(!as_generator( (namespaces @@ -71,6 +75,9 @@ struct class_implementation_generator )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, cpp_namespaces, cls.cxx_name, cls.parts), ctx)) return false; + if(!as_generator(ignore_warning_end).generate(sink, nullptr, ctx)) + return false; + if(!as_generator("#endif\n").generate(sink, std::make_tuple(), ctx)) return false; diff --git a/src/lib/eolian_cxx/grammar/generator.hpp b/src/lib/eolian_cxx/grammar/generator.hpp index 6d0be7e4f1..25fff51ff7 100644 --- a/src/lib/eolian_cxx/grammar/generator.hpp +++ b/src/lib/eolian_cxx/grammar/generator.hpp @@ -46,7 +46,7 @@ struct is_eager_generator : is_eager_generator {}; // struct is_generator : is_eager_generator {}; template ::value>::type> -G as_generator(G&& g) { return g; } +G as_generator(G g) { return g; } } } } diff --git a/src/lib/eolian_cxx/grammar/header.hpp b/src/lib/eolian_cxx/grammar/header.hpp index 29435404dd..f749584163 100644 --- a/src/lib/eolian_cxx/grammar/header.hpp +++ b/src/lib/eolian_cxx/grammar/header.hpp @@ -11,6 +11,7 @@ #include "class_definition.hpp" #include "class_declaration.hpp" #include "implementation_include_directive.hpp" +#include "ignore_warning.hpp" namespace efl { namespace eolian { namespace grammar { @@ -27,11 +28,13 @@ auto class_header = << *class_declaration // sequence | class << *class_forward_declaration // sequence | class << string // extra header + << ignore_warning_begin << "\nnamespace eo_cxx {\n" << *base_class_definition // sequence | class << "}\n" << *class_definition // sequence | class // << *implementation_include_directive + << ignore_warning_end ] ; diff --git a/src/lib/eolian_cxx/grammar/ignore_warning.hpp b/src/lib/eolian_cxx/grammar/ignore_warning.hpp new file mode 100644 index 0000000000..d3d2a6e3d1 --- /dev/null +++ b/src/lib/eolian_cxx/grammar/ignore_warning.hpp @@ -0,0 +1,48 @@ +#ifndef EOLIAN_CXX_IGNORE_WARNING_HH +#define EOLIAN_CXX_IGNORE_WARNING_HH + +#include "grammar/generator.hpp" + +namespace efl { namespace eolian { namespace grammar { + +struct ignore_warning_begin_generator +{ + template + bool generate(OutputIterator sink, attributes::unused_type, Context const& context) const + { + return as_generator( + "\n" + "#pragma GCC diagnostic push\n" + "#pragma GCC diagnostic ignored \"-Wignored-qualifiers\"\n" + "\n" + ).generate(sink, nullptr, context); + } +}; + +struct ignore_warning_end_generator +{ + template + bool generate(OutputIterator sink, attributes::unused_type, Context const& context) const + { + return as_generator( + "\n#pragma GCC diagnostic pop\n\n" + ).generate(sink, nullptr, context); + } +}; + +template <> +struct is_eager_generator : std::true_type {}; +template <> +struct is_generator : std::true_type {}; + +template <> +struct is_eager_generator : std::true_type {}; +template <> +struct is_generator : std::true_type {}; + +ignore_warning_begin_generator constexpr ignore_warning_begin = {}; +ignore_warning_end_generator constexpr ignore_warning_end = {}; + +} } } + +#endif diff --git a/src/lib/eolian_cxx/grammar/type_impl.hpp b/src/lib/eolian_cxx/grammar/type_impl.hpp index ca73a14bd0..c5bd4d8363 100644 --- a/src/lib/eolian_cxx/grammar/type_impl.hpp +++ b/src/lib/eolian_cxx/grammar/type_impl.hpp @@ -348,7 +348,7 @@ struct visitor_generate // pointers.swap(no_pointer_regular.pointers); // if(is_out) // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true}); - return visitor_type{sink, context, c_type, false}(no_pointer_regular) + return visitor_type{sink, context, c_type, false, false}(no_pointer_regular) && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context) ; // && detail::generate_pointers(sink, pointers, *context, false); diff --git a/src/lib/ephysics/ephysics_quaternion.cpp b/src/lib/ephysics/ephysics_quaternion.cpp index 899204d563..bf1b91548e 100644 --- a/src/lib/ephysics/ephysics_quaternion.cpp +++ b/src/lib/ephysics/ephysics_quaternion.cpp @@ -126,7 +126,6 @@ ephysics_quaternion_euler_set(EPhysics_Quaternion *quat, double yaw, double pitc return; } - bt_quat = btQuaternion(); bt_quat.setEuler(yaw / RAD_TO_DEG, pitch / RAD_TO_DEG, roll / RAD_TO_DEG); _ephysics_quaternion_update(quat, &bt_quat); } diff --git a/src/lib/evas/Evas_Loader.h b/src/lib/evas/Evas_Loader.h index 787df4e81f..94ec424209 100644 --- a/src/lib/evas/Evas_Loader.h +++ b/src/lib/evas/Evas_Loader.h @@ -70,7 +70,7 @@ extern "C" { #endif /* the module api version */ -#define EVAS_MODULE_API_VERSION 2 +#define EVAS_MODULE_API_VERSION 3 /* the module types */ typedef enum _Evas_Module_Type @@ -130,7 +130,25 @@ struct _Evas_Image_Load_Opts }; typedef Emile_Image_Animated Evas_Image_Animated; -typedef Emile_Image_Property Evas_Image_Property; +typedef struct _Evas_Image_Property Evas_Image_Property; + +struct _Evas_Image_Property +{ + Emile_Image_Property info; + // Stretch region are directly encoded the way Evas excpect them internally + // 8bits is used for each step. The lower bits indicate how long the stretch region + // span. Masking with 0x80 will be true if the region is stretchable. If false, it + // will be fixed size. + struct { + struct { + uint8_t *region; + } horizontal, vertical; + } stretch; + // Where inside the image are we supposed to overlay data + Eina_Rectangle content; + // need_data is set to True when to get accurate property, data need to be loaded + Eina_Bool need_data; +}; typedef struct _Evas_Image_Load_Func Evas_Image_Load_Func; @@ -186,8 +204,11 @@ typedef Emile_Colorspace Evas_Colorspace; /**< Colorspaces for pixel data suppor #define EVAS_COLORSPACE_RGBA_S3TC_DXT4 EMILE_COLORSPACE_RGBA_S3TC_DXT4 #define EVAS_COLORSPACE_RGBA_S3TC_DXT5 EMILE_COLORSPACE_RGBA_S3TC_DXT5 +#define EVAS_IMAGE_LOAD_VERSION 2 + struct _Evas_Image_Load_Func { + int version; void *(*file_open) (Eina_File *f, Eina_Stringshare *key, Evas_Image_Load_Opts *opts, Evas_Image_Animated *animated, @@ -195,11 +216,14 @@ struct _Evas_Image_Load_Func void (*file_close) (void *loader_data); Eina_Bool (*file_head) (void *loader_data, - Evas_Image_Property *prop, - int *error); + Evas_Image_Property *prop, + int *error); + Eina_Bool (*file_head_with_data) (void *loader_data, + Evas_Image_Property *prop, + void *pixels, int *error); Eina_Bool (*file_data) (void *loader_data, - Evas_Image_Property *prop, - void *pixels, int *error); + Evas_Image_Property *prop, + void *pixels, int *error); double (*frame_duration) (void *loader_data, int start, int frame_num); @@ -240,6 +264,32 @@ EAPI Eina_Bool evas_module_task_cancelled (void); /**< @since 1.19 */ EINA_MODULE_INIT(evas_##Tn##_##Name##_init); \ EINA_MODULE_SHUTDOWN(evas_##Tn##_##Name##_shutdown); +static inline Eina_Bool +evas_loader_helper_stretch_region_push(uint8_t **region, + uint8_t *offset, + Eina_Bool stretchable) +{ + uint32_t length = 0; + void *tmp; + + if (*offset == 0) return EINA_TRUE; + + while (*region && (*region)[length] != 0) + length++; + + // +1 for termination and +1 for the region being pushed + tmp = realloc(*region, sizeof (uint8_t) * (length + 2)); + if (!tmp) return EINA_FALSE; + + *region = (uint8_t *) tmp; + (*region)[length] = (*offset) | (stretchable ? 0x80 : 0); + (*region)[length + 1] = 0; + + *offset = 0; + + return EINA_TRUE; +} + #ifdef __cplusplus } #endif diff --git a/src/lib/evas/canvas/efl_canvas_image_internal.eo b/src/lib/evas/canvas/efl_canvas_image_internal.eo index 20777020a8..98cf4949d9 100644 --- a/src/lib/evas/canvas/efl_canvas_image_internal.eo +++ b/src/lib/evas/canvas/efl_canvas_image_internal.eo @@ -11,12 +11,14 @@ abstract @beta Efl.Canvas.Image_Internal extends Efl.Canvas.Object implements Ef Efl.Object.finalize; Efl.Object.debug_name_override; Efl.File_Save.save; - Efl.Gfx.Image_Orientable.orientation { get; set; } + Efl.Gfx.Image_Orientable.image_orientation { get; set; } Efl.Gfx.Image.smooth_scale { get; set; } Efl.Gfx.Image.ratio { get; } + Efl.Gfx.Image.content_region { get; } Efl.Gfx.Image.border { get; set; } Efl.Gfx.Image.border_scale { get; set; } Efl.Gfx.Image.border_center_fill { get; set; } + Efl.Gfx.Image.stretch_region { get; set; } Efl.Gfx.Image.scale_hint { get; set; } Efl.Gfx.Image.content_hint { get; set; } Efl.Gfx.Image.image_size { get; } diff --git a/src/lib/evas/canvas/efl_input_event.eo b/src/lib/evas/canvas/efl_input_event.eo index 04bc589a86..9194b0bc9b 100644 --- a/src/lib/evas/canvas/efl_input_event.eo +++ b/src/lib/evas/canvas/efl_input_event.eo @@ -1,6 +1,6 @@ import efl_input_types; -mixin @beta Efl.Input.Event requires Efl.Object extends Efl.Duplicate +mixin Efl.Input.Event requires Efl.Object extends Efl.Duplicate { [[Represents a generic event data. diff --git a/src/lib/evas/canvas/efl_input_hold.eo b/src/lib/evas/canvas/efl_input_hold.eo index d5f939f341..9649d75cb6 100644 --- a/src/lib/evas/canvas/efl_input_hold.eo +++ b/src/lib/evas/canvas/efl_input_hold.eo @@ -1,4 +1,4 @@ -class @beta Efl.Input.Hold extends Efl.Object implements Efl.Input.Event +class Efl.Input.Hold extends Efl.Object implements Efl.Input.Event { [[Event data sent when inputs are put on hold or resumed.]] methods { diff --git a/src/lib/evas/canvas/efl_input_interface.eo b/src/lib/evas/canvas/efl_input_interface.eo index e232ec169a..8ab2fa6f81 100644 --- a/src/lib/evas/canvas/efl_input_interface.eo +++ b/src/lib/evas/canvas/efl_input_interface.eo @@ -1,4 +1,4 @@ -interface @beta Efl.Input.Interface +interface Efl.Input.Interface { [[An object implementing this interface can send pointer events. diff --git a/src/lib/evas/canvas/efl_input_key.eo b/src/lib/evas/canvas/efl_input_key.eo index a14e81c64a..062d02e91f 100644 --- a/src/lib/evas/canvas/efl_input_key.eo +++ b/src/lib/evas/canvas/efl_input_key.eo @@ -1,4 +1,4 @@ -class @beta Efl.Input.Key extends Efl.Object implements Efl.Input.Event, Efl.Input.State +class Efl.Input.Key extends Efl.Object implements Efl.Input.Event, Efl.Input.State { [[Represents a single key event from a keyboard or similar device. ]] diff --git a/src/lib/evas/canvas/efl_input_pointer.eo b/src/lib/evas/canvas/efl_input_pointer.eo index f50b511d20..dd31ad4453 100644 --- a/src/lib/evas/canvas/efl_input_pointer.eo +++ b/src/lib/evas/canvas/efl_input_pointer.eo @@ -1,6 +1,6 @@ import efl_input_types; -class @beta Efl.Input.Pointer extends Efl.Object implements Efl.Input.Event, Efl.Input.State +class Efl.Input.Pointer extends Efl.Object implements Efl.Input.Event, Efl.Input.State { [[Event data carried over with any pointer event (mouse, touch, pen, ...) ]] @@ -11,7 +11,7 @@ class @beta Efl.Input.Pointer extends Efl.Object implements Efl.Input.Event, Efl act: Efl.Pointer.Action; [[Event action]] } } - @property value_has { + @property value_has @beta { [[$true if this event carries a valid value for the specified $key.]] get {} keys { @@ -21,7 +21,7 @@ class @beta Efl.Input.Pointer extends Efl.Object implements Efl.Input.Event, Efl has: bool; [[$true if input value is valid, $false otherwise]] } } - @property value { + @property value @beta { [[Represents a generic value for this event. Refer to the documentation of @Efl.Input.Value for each value's diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c index 83c1f2fcd7..5ffcd1f9a2 100644 --- a/src/lib/evas/canvas/evas_events.c +++ b/src/lib/evas/canvas/evas_events.c @@ -1851,6 +1851,38 @@ _canvas_event_feed_mouse_up_internal(Evas_Public_Data *e, Efl_Input_Pointer_Data _evas_event_source_mouse_up_events(eo_obj, eo_e, evt, pdata, event_id, cancel); if (e->delete_me) break; } + else if (evas_event_freezes_through(eo_obj, obj) && + (obj->proxy->is_proxy) && (obj->proxy->src_events)) + { + Evas_Object *eo_src = _evas_object_image_source_get(eo_obj); + Evas_Object_Protected_Data *src = efl_data_scope_get(eo_src, EFL_CANVAS_OBJECT_CLASS); + Evas_Object_Protected_Data *child; + Evas_Object *eo_child; + Eina_List *copy_events; + + if (src->delete_me) continue; + copy_events = evas_event_list_copy(src->proxy->src_event_in); + EINA_LIST_FREE(copy_events, eo_child) + { + Evas_Object_Pointer_Data *obj_pdata; + + child = efl_data_scope_get(eo_child, EFL_CANVAS_OBJECT_CLASS); + obj_pdata = _evas_object_pointer_data_get(pdata, child); + if (!obj_pdata) + { + ERR("Could not find the object pointer data for device %p", + ev->device); + continue; + } + if (((obj_pdata->pointer_mode == EVAS_OBJECT_POINTER_MODE_AUTOGRAB) || + (obj_pdata->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN)) && + (obj_pdata->mouse_grabbed > 0)) + { + obj_pdata->mouse_grabbed--; + pdata->seat->mouse_grabbed--; + } + } + } if (pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) { if ((!cancel) && (pdata->seat->nogrep > 0)) pdata->seat->nogrep--; diff --git a/src/lib/evas/canvas/evas_image_private.h b/src/lib/evas/canvas/evas_image_private.h index 3fe76324fe..664d60e684 100644 --- a/src/lib/evas/canvas/evas_image_private.h +++ b/src/lib/evas/canvas/evas_image_private.h @@ -75,6 +75,13 @@ struct _Evas_Object_Image_State short l, r, t, b; unsigned char fill; } border; + struct { + struct { + uint8_t *region; + uint32_t stretchable; + uint32_t total; + } horizontal, vertical; + } stretch; Evas_Object *source; Evas_Map *defmap; @@ -91,6 +98,9 @@ struct _Evas_Object_Image_State Eina_Bool has_alpha :1; Eina_Bool opaque_valid : 1; Eina_Bool opaque : 1; + + Eina_Bool free_stretch : 1; // Should we free stretch region? + Eina_Bool stretch_loaded : 1; // Is the stretch region loaded from file? }; #define EVAS_IMAGE_PRELOAD_NONE 0x00 diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 081c42aabe..50a064a287 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -14,6 +14,9 @@ static Evas_Coord evas_object_image_figure_x_fill(Evas_Object *eo_obj, Evas_Ob static Evas_Coord evas_object_image_figure_y_fill(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret); static void evas_object_image_init(Evas_Object *eo_obj); + +static inline uint32_t _stretch_region_accumulate(uint8_t *stretch_region, Eina_Bool mask, uint32_t *i); + static void evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, void *type_private_data, void *engine, void *output, void *context, void *surface, @@ -92,6 +95,7 @@ static const Evas_Object_Image_State default_state = { { 0, 0, 0, 0 }, // fill { 0, 0, 0 }, // image { 1.0, 0, 0, 0, 0, 1 }, // border + { { NULL, 0, 0 }, { NULL, 0, 0 } }, NULL, NULL, NULL, //source, defmap, scene NULL, //f NULL, //key @@ -412,7 +416,7 @@ _evas_image_orientation_set(Eo *eo_obj, Evas_Image_Data *o, Evas_Image_Orient or } EOLIAN static void -_efl_canvas_image_internal_efl_gfx_image_orientable_orientation_set(Eo *obj, Evas_Image_Data *o, Efl_Gfx_Image_Orientation efl_orient) +_efl_canvas_image_internal_efl_gfx_image_orientable_image_orientation_set(Eo *obj, Evas_Image_Data *o, Efl_Gfx_Image_Orientation efl_orient) { // This array takes an Efl_Gfx_Image_Orientation and turns it into an Elm_Image_Orient static const Evas_Image_Orient evas_orient[16] = { @@ -440,7 +444,7 @@ _efl_canvas_image_internal_efl_gfx_image_orientable_orientation_set(Eo *obj, Eva } EOLIAN static Efl_Gfx_Image_Orientation -_efl_canvas_image_internal_efl_gfx_image_orientable_orientation_get(const Eo *obj EINA_UNUSED, Evas_Image_Data *o) +_efl_canvas_image_internal_efl_gfx_image_orientable_image_orientation_get(const Eo *obj EINA_UNUSED, Evas_Image_Data *o) { return o->orient_value; } @@ -461,6 +465,130 @@ _efl_canvas_image_internal_efl_object_dbg_info_get(Eo *eo_obj, Evas_Image_Data * (uint64_t)(uintptr_t)evas_object_image_source_get(eo_obj)); } +static void +_stretch_region_load(Evas_Object_Protected_Data *obj, Evas_Image_Data *o) +{ + unsigned int i; + uint8_t *horizontal = NULL; + uint8_t *vertical = NULL; + uint32_t total, stretchable; + + if (o->cur->stretch_loaded == EINA_TRUE || + (o->cur->stretch.horizontal.region && o->cur->stretch.vertical.region)) + return ; + + ENFN->image_stretch_region_get(ENC, o->engine_data, + &horizontal, + &vertical); + + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + { + state_write->stretch.horizontal.region = horizontal; + state_write->stretch.vertical.region = vertical; + state_write->free_stretch = EINA_FALSE; + state_write->stretch_loaded = EINA_TRUE; + } + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write); + + if (!o->cur->stretch.horizontal.region || !o->cur->stretch.vertical.region) + return ; + + stretchable = 0; + total = 0; + for (i = 0; o->cur->stretch.horizontal.region[i]; i++) + { + total += o->cur->stretch.horizontal.region[i] & 0x7F; + if (o->cur->stretch.horizontal.region[i] & 0x80) + stretchable += o->cur->stretch.horizontal.region[i] & 0x7F; + } + + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + { + state_write->stretch.horizontal.stretchable = stretchable; + state_write->stretch.horizontal.total = total; + } + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write); + + stretchable = 0; + total = 0; + for (i = 0; o->cur->stretch.vertical.region[i]; i++) + { + total += o->cur->stretch.vertical.region[i] & 0x7F; + if (o->cur->stretch.vertical.region[i] & 0x80) + stretchable += o->cur->stretch.vertical.region[i] & 0x7F; + } + + EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write) + { + state_write->stretch.vertical.stretchable = stretchable; + state_write->stretch.vertical.total = total; + } + EINA_COW_IMAGE_STATE_WRITE_END(o, state_write); +} + +static Eina_Rect +_efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Evas_Image_Data *o) +{ + Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + Eina_Rect r; + + if (!o->cur->stretch.horizontal.region && + !o->cur->stretch.vertical.region) + _stretch_region_load(obj, o); + + if (o->cur->stretch.horizontal.region && + o->cur->stretch.vertical.region) + { + uint32_t acc; + uint32_t hi = 0; + uint32_t vi = 0; + + // If the file come with a defined content zone, then return it + if (ENFN->image_content_region_get(ENC, o->engine_data, &r.rect)) + { + // Correct bottom right corner coordinate to be resized with object size + r.w = obj->cur->geometry.w - (o->cur->image.w - r.w); + r.h = obj->cur->geometry.h - (o->cur->image.h - r.h); + return r; + } + + r.x = _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0, &hi); + r.w = o->cur->stretch.horizontal.stretchable + obj->cur->geometry.w - o->cur->image.w; + + // Accumulate all the non stretch zone, except the first one and the last one + acc = 0; + while (o->cur->stretch.horizontal.region[hi]) + { + // We are just ignoring all the stretchable zone as we know them already + _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0x80, &hi); + r.w += acc; + acc = _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0, &hi); + } + + r.y = _stretch_region_accumulate(o->cur->stretch.vertical.region, 0, &vi); + r.h = o->cur->stretch.vertical.stretchable + obj->cur->geometry.h - o->cur->image.h; + + // Accumulate all the stretch zone, except the last non stretching one + acc = 0; + while (o->cur->stretch.vertical.region[vi]) + { + // We are just ignoring all the stretchable zone as we know them already + _stretch_region_accumulate(o->cur->stretch.vertical.region, 0x80, &vi); + r.h += acc; + acc = _stretch_region_accumulate(o->cur->stretch.vertical.region, 0, &vi); + } + } + else + { + r.x = o->cur->border.l; + r.y = o->cur->border.t; + r.w = obj->cur->geometry.w - o->cur->border.l - o->cur->border.r; + r.h = obj->cur->geometry.h - o->cur->border.t - o->cur->border.b; + } + + return r; +} + EOLIAN static void _efl_canvas_image_internal_efl_gfx_image_border_set(Eo *eo_obj, Evas_Image_Data *o, int l, int r, int t, int b) { @@ -531,6 +659,276 @@ _toggle_fill_listener(Eo *eo_obj, Evas_Image_Data *o) NULL); } +static inline Eina_Bool +_efl_canvas_image_internal_stretch_region_push(uint8_t **stretch_region, + uint32_t *stretch_region_length, + const uint8_t region) +{ + uint8_t *tmp; + + tmp = realloc(*stretch_region, (*stretch_region_length + 1) * sizeof (uint8_t)); + if (!tmp) return EINA_FALSE; + *stretch_region = tmp; + (*stretch_region)[*stretch_region_length] = region; + (*stretch_region_length) += 1; + + return EINA_TRUE; +} + +static inline Eina_Error +_efl_canvas_image_internal_stretch_region_build(uint8_t **stretch_region, + uint32_t *stretch_region_length, + uint32_t value, uint8_t mask) +{ + while (value > 0x7F) + { + if (!_efl_canvas_image_internal_stretch_region_push(stretch_region, + stretch_region_length, + mask | 0x7F)) + { + free(*stretch_region); + return ENOMEM; + } + + value -= 0x7F; + } + + if (!value) return 0; + + if (!_efl_canvas_image_internal_stretch_region_push(stretch_region, + stretch_region_length, + mask | value)) + { + free(*stretch_region); + return ENOMEM; + } + + return 0; +} + +static inline uint8_t * +_efl_canvas_image_internal_stretch_region_iterate(Eina_Iterator *it) +{ + Efl_Gfx_Image_Stretch_Region sz; + uint8_t *stretch_region = NULL; + uint32_t stretch_region_length = 0; + + EINA_ITERATOR_FOREACH(it, sz) + { + if (_efl_canvas_image_internal_stretch_region_build(&stretch_region, + &stretch_region_length, + sz.offset, 0)) + return NULL; + + // The upper bit means stretchable region if set + if (_efl_canvas_image_internal_stretch_region_build(&stretch_region, + &stretch_region_length, + sz.length, 0x80)) + return NULL; + } + + if (!_efl_canvas_image_internal_stretch_region_push(&stretch_region, + &stretch_region_length, + 0)) + { + free(stretch_region); + return NULL; + } + + return stretch_region; +} + +static Eina_Error +_efl_canvas_image_internal_efl_gfx_image_stretch_region_set(Eo *eo_obj, Evas_Image_Data *pd, + Eina_Iterator *horizontal, + Eina_Iterator *vertical) +{ + uint8_t *fhsz = NULL, *fvsz = NULL, *walk; + uint32_t hstretch = 0, vstretch = 0; + uint32_t htotal = 0, vtotal = 0; + Eina_Error err = EINVAL; + Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + + // We do not duplicate the stretch region in memory, just move pointer. So when + // we do change it, we have to make sure nobody is accessing them anymore by + // blocking rendering. + evas_object_async_block(obj); + EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write) + { + if (state_write->free_stretch) free(state_write->stretch.horizontal.region); + state_write->stretch.horizontal.region = NULL; + + if (state_write->free_stretch) free(state_write->stretch.vertical.region); + state_write->stretch.vertical.region = NULL; + + state_write->free_stretch = EINA_FALSE; + state_write->stretch_loaded = EINA_FALSE; + } + EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write); + + if (!horizontal && !vertical) return 0; + if (!horizontal || !vertical) goto on_error; + + err = ENOMEM; + + fhsz = _efl_canvas_image_internal_stretch_region_iterate(horizontal); + if (!fhsz) goto on_error; + fvsz = _efl_canvas_image_internal_stretch_region_iterate(vertical); + if (!fvsz) goto on_error; + + for (walk = fhsz; *walk; walk++) + { + if ((*walk & 0x80)) hstretch += *walk & 0x7F; + htotal += *walk & 0x7F; + } + + for (walk = fvsz; *walk; walk++) + { + if ((*walk & 0x80)) vstretch += *walk & 0x7F; + vtotal += *walk & 0x7F; + } + + eina_iterator_free(horizontal); + eina_iterator_free(vertical); + + EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write) + { + state_write->stretch.horizontal.region = fhsz; + state_write->stretch.horizontal.stretchable = hstretch; + state_write->stretch.horizontal.total = htotal; + state_write->stretch.vertical.region = fvsz; + state_write->stretch.vertical.stretchable = vstretch; + state_write->stretch.vertical.total = vtotal; + state_write->free_stretch = EINA_TRUE; + state_write->stretch_loaded = EINA_TRUE; + } + EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write); + + return 0; + + on_error: + eina_iterator_free(horizontal); + eina_iterator_free(vertical); + free(fhsz); + free(fvsz); + + return err; +} + +typedef struct _Efl_Gfx_Image_Stretch_Region_Iterator Efl_Gfx_Image_Stretch_Region_Iterator; +struct _Efl_Gfx_Image_Stretch_Region_Iterator +{ + Eina_Iterator iterator; + + Efl_Gfx_Image_Stretch_Region sz; + + uint8_t *stretch_region; + unsigned int next; +}; + +static Eina_Bool +_efl_gfx_image_stretch_region_iterator_next(Eina_Iterator *iterator, void **data) +{ + Efl_Gfx_Image_Stretch_Region_Iterator *it = (Efl_Gfx_Image_Stretch_Region_Iterator*) iterator; + + *data = &it->sz; + if (!it->stretch_region[it->next]) return EINA_FALSE; + + it->sz.offset = 0; + it->sz.length = 0; + + // Count offset before next stretch region + while (!(it->stretch_region[it->next] & 0x80) && it->stretch_region[it->next]) + { + it->sz.offset += it->stretch_region[it->next] & 0x7F; + it->next++; + } + + // Count length of the stretch region + while ((it->stretch_region[it->next] & 0x80) && it->stretch_region[it->next]) + { + it->sz.length += it->stretch_region[it->next] & 0x7F; + it->next++; + } + + return EINA_TRUE; +} + +static void * +_efl_gfx_image_stretch_region_iterator_container(Eina_Iterator *it EINA_UNUSED) +{ + return NULL; +} + +static void +_efl_gfx_image_stretch_region_iterator_free(Eina_Iterator *it) +{ + free(it); +} + +static void +_efl_canvas_image_internal_efl_gfx_image_stretch_region_get(const Eo *eo_obj, + Evas_Image_Data *pd, + Eina_Iterator **horizontal, + Eina_Iterator **vertical) +{ + Efl_Gfx_Image_Stretch_Region_Iterator *it; + + if (!pd->cur->stretch.vertical.region && + !pd->cur->stretch.horizontal.region) + { + Evas_Object_Protected_Data *obj; + + obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + _stretch_region_load(obj, pd); + } + + if (!horizontal) goto vertical_only; + if (!pd->cur->stretch.horizontal.region) + { + *horizontal = NULL; + goto vertical_only; + } + + it = calloc(1, sizeof (Efl_Gfx_Image_Stretch_Region_Iterator)); + if (!it) return; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->stretch_region = pd->cur->stretch.horizontal.region; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_efl_gfx_image_stretch_region_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _efl_gfx_image_stretch_region_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_efl_gfx_image_stretch_region_iterator_free); + + *horizontal = &it->iterator; + + vertical_only: + if (!vertical) return; + if (!pd->cur->stretch.vertical.region) + { + *vertical = NULL; + return; + } + + it = calloc(1, sizeof (Efl_Gfx_Image_Stretch_Region_Iterator)); + if (!it) return; + + EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); + + it->stretch_region = pd->cur->stretch.vertical.region; + + it->iterator.version = EINA_ITERATOR_VERSION; + it->iterator.next = FUNC_ITERATOR_NEXT(_efl_gfx_image_stretch_region_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER( + _efl_gfx_image_stretch_region_iterator_container); + it->iterator.free = FUNC_ITERATOR_FREE(_efl_gfx_image_stretch_region_iterator_free); + + *vertical = &it->iterator; +} + EOLIAN static void _efl_canvas_image_internal_efl_gfx_fill_fill_auto_set(Eo *eo_obj, Evas_Image_Data *o, Eina_Bool setting) { @@ -1286,6 +1684,7 @@ _efl_canvas_image_internal_efl_object_destructor(Eo *eo_obj, Evas_Image_Data *o if (obj->legacy.ctor) evas_object_image_video_surface_set(eo_obj, NULL); evas_object_image_free(eo_obj, obj); + efl_gfx_image_stretch_region_set(eo_obj, NULL, NULL); efl_destructor(efl_super(eo_obj, MY_CLASS)); } @@ -1966,6 +2365,84 @@ _evas_image_pixels_get(Eo *eo_obj, Evas_Object_Protected_Data *obj, return pixels; } +static inline uint32_t +_stretch_region_accumulate(uint8_t *stretch_region, Eina_Bool mask, uint32_t *i) +{ + uint32_t acc; + + for (acc = 0; + ((stretch_region[*i] & 0x80) == mask) && stretch_region[*i]; + (*i)++) + acc += stretch_region[*i] & 0x7F; + + return acc; +} + +static void +_evas_image_render_hband(Evas_Object_Protected_Data *obj, Evas_Image_Data *o, + void *engine, void *output, void *context, + void *surface, void *pixels, + const int *imw, const int *imh EINA_UNUSED, + int stretchw, int stretchh EINA_UNUSED, + int *inx, int *iny, int *inw, int *inh, + int *outx, int *outy, int *outw, int *outh, + Eina_Bool do_async) +{ + uint32_t hacc; + uint32_t hi; + + if (*inh == 0 || *outh == 0) goto end; + + hi = 0; + while (o->cur->stretch.horizontal.region[hi]) + { + // Not stretched horizontal + hacc = _stretch_region_accumulate(o->cur->stretch.horizontal.region, + 0, &hi); + *inw = hacc; + *outw = hacc; + + if (*inw && *outw) + _draw_image(obj, engine, output, context, surface, pixels, + *inx, *iny, *inw, *inh, + *outx, *outy, *outw, *outh, + o->cur->smooth_scale, do_async); + + // We always step before starting the new region + *inx += *inw; + *outx += *outw; + + // Horizontal stretched + hacc = _stretch_region_accumulate(o->cur->stretch.horizontal.region, + 0x80, &hi); + *inw = hacc; + *outw = hacc * stretchw / o->cur->stretch.horizontal.stretchable; + + if (*inw) + _draw_image(obj, engine, output, context, surface, pixels, + *inx, *iny, *inw, *inh, + *outx, *outy, *outw, *outh, + o->cur->smooth_scale, do_async); + + // We always step before starting the new region + *inx += *inw; + *outx += *outw; + } + // Finish end of image, not horizontally stretched + *inw = *imw - *inx; + *outw = *inw; // If my math are correct, this should be equal + + if (*inw) + _draw_image(obj, engine, output, context, surface, pixels, + *inx, *iny, *inw, *inh, + *outx, *outy, *outw, *outh, + o->cur->smooth_scale, do_async); + + end: + *iny += *inh; // We always step before starting the next region + *outy += *outh; +} + static void _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, void *engine, void *output, void *context, void *surface, int x, int y, @@ -1996,6 +2473,8 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, return; } + _stretch_region_load(obj, o); + ENFN->image_scale_hint_set(engine, pixels, o->scale_hint); idx = evas_object_image_figure_x_fill(eo_obj, obj, o->cur->fill.x, o->cur->fill.w, &idw); idy = evas_object_image_figure_y_fill(eo_obj, obj, o->cur->fill.y, o->cur->fill.h, &idh); @@ -2050,7 +2529,82 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, if (ih <= 0) break; } - if ((o->cur->border.l == 0) && (o->cur->border.r == 0) && + if (o->cur->stretch.horizontal.region && + o->cur->stretch.vertical.region) + { + int inx, iny, inw, inh, outx, outy, outw, outh; + int ox, oy; + int imw, imh; + int stretchh, stretchw; + uint32_t vacc; + uint32_t vi; + + imw = imagew; + imh = imageh; + ox = offx + ix; + oy = offy + iy; + iny = 0; + outy = oy; + + // Check that the image is something we can deal with + if (imw < (int) o->cur->stretch.horizontal.total || + imh < (int) o->cur->stretch.vertical.total) + break; + + // Calculate the amount to stretch, by removing from the targetted size + // the amount that should not stretch from the source image + stretchw = iw - (imw - o->cur->stretch.horizontal.stretchable); + stretchh = ih - (imh - o->cur->stretch.vertical.stretchable); + + // Check we have room to stretch + if (stretchh < 0) stretchh = 0; + if (stretchw < 0) stretchw = 0; + + for (vi = 0; o->cur->stretch.vertical.region[vi]; ) + { + vacc = _stretch_region_accumulate(o->cur->stretch.vertical.region, 0, &vi); + inx = 0; + outx = ox; + + // Not stretching vertically step + inh = vacc; + outh = vacc; + + _evas_image_render_hband(obj, o, engine, output, context, + surface, pixels, + &imw, &imh, stretchw, stretchh, + &inx, &iny, &inw, &inh, + &outx, &outy, &outw, &outh, + do_async); + + // Stretching vertically step + vacc = _stretch_region_accumulate(o->cur->stretch.vertical.region, 0x80, &vi); + inx = 0; + outx = ox; + inh = vacc; + outh = vacc * stretchh / o->cur->stretch.vertical.stretchable; + + _evas_image_render_hband(obj, o, engine, output, context, + surface, pixels, + &imw, &imh, stretchw, stretchh, + &inx, &iny, &inw, &inh, + &outx, &outy, &outw, &outh, + do_async); + } + // Finish end of image, not stretched vertical, not stretched horizontal + inx = 0; + outx = ox; + inh = imh - iny; + outh = inh; // Again, if my math are correct, this should be the same + + _evas_image_render_hband(obj, o, engine, output, context, + surface, pixels, + &imw, &imh, stretchw, stretchh, + &inx, &iny, &inw, &inh, + &outx, &outy, &outw, &outh, + do_async); + } + else if ((o->cur->border.l == 0) && (o->cur->border.r == 0) && (o->cur->border.t == 0) && (o->cur->border.b == 0) && (o->cur->border.fill != 0)) { diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index 87934be5e4..074dc1d618 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -3625,11 +3625,16 @@ evas_render_updates_internal(Evas *eo_e, obj = eina_array_data_get(&e->pending_objects, i); if (obj->smart.parent) { + /* these are all objects which could not be rendered because they were + * added to their smart parent in this cycle and the parent was not changed + */ Evas_Object_Protected_Data *smart_parent; smart_parent = efl_data_scope_get(obj->smart.parent, EFL_CANVAS_OBJECT_CLASS); evas_object_change(obj->smart.parent, smart_parent); + /* render cache must be invalidated to correctly render subobj on next pass */ + evas_object_smart_render_cache_clear(obj->smart.parent); } obj->changed = EINA_TRUE; } diff --git a/src/lib/evas/common/evas_image_load.c b/src/lib/evas/common/evas_image_load.c index 7d4ca66790..611767448e 100644 --- a/src/lib/evas/common/evas_image_load.c +++ b/src/lib/evas/common/evas_image_load.c @@ -183,7 +183,7 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error) evas_image_load_func = em->functions; evas_module_use(em); *error = EVAS_LOAD_ERROR_NONE; - if (evas_image_load_func) + if (evas_image_load_func && evas_image_load_func->version == EVAS_IMAGE_LOAD_VERSION) { Evas_Image_Property property; const char *file; @@ -215,17 +215,18 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error) DBG("loaded file head using module '%s' (%p): %s", em->definition->name, em, file); - ie->w = property.w; - ie->h = property.h; - ie->borders.l = property.borders.l; - ie->borders.r = property.borders.r; - ie->borders.t = property.borders.t; - ie->borders.b = property.borders.b; - ie->scale = property.scale; - ie->flags.alpha = property.alpha; - if (property.cspaces) ie->cspaces = property.cspaces; - ie->flags.rotated = property.rotated; - ie->flags.flipped = property.flipped; + ie->w = property.info.w; + ie->h = property.info.h; + ie->borders.l = property.info.borders.l; + ie->borders.r = property.info.borders.r; + ie->borders.t = property.info.borders.t; + ie->borders.b = property.info.borders.b; + ie->scale = property.info.scale; + ie->flags.alpha = property.info.alpha; + ie->need_data = property.need_data; + if (property.info.cspaces) ie->cspaces = property.info.cspaces; + ie->flags.rotated = property.info.rotated; + ie->flags.flipped = property.info.flipped; r = EINA_FALSE; } else @@ -448,20 +449,20 @@ end: _timestamp_build(&(ie->tstamp), &st); memset(&property, 0, sizeof (property)); - property.w = ie->w; - property.h = ie->h; - property.scale = ie->scale; - property.rotated = ie->flags.rotated; - property.flipped = ie->flags.flipped; - property.premul = EINA_FALSE; - property.alpha_sparse = EINA_FALSE; - property.cspace = ie->space; + property.info.w = ie->w; + property.info.h = ie->h; + property.info.scale = ie->scale; + property.info.rotated = ie->flags.rotated; + property.info.flipped = ie->flags.flipped; + property.info.premul = EINA_FALSE; + property.info.alpha_sparse = EINA_FALSE; + property.info.cspace = ie->space; evas_cache_image_surface_alloc(ie, ie->w, ie->h); - property.borders.l = ie->borders.l; - property.borders.r = ie->borders.r; - property.borders.t = ie->borders.t; - property.borders.b = ie->borders.b; + property.info.borders.l = ie->borders.l; + property.info.borders.r = ie->borders.r; + property.info.borders.t = ie->borders.t; + property.info.borders.b = ie->borders.b; pixels = evas_cache_image_pixels(ie); if (!pixels) @@ -470,11 +471,21 @@ end: return EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; } - evas_image_load_func->file_data(ie->loader_data, &property, pixels, &ret); + if (ie->need_data) + { + evas_image_load_func->file_head_with_data(ie->loader_data, &property, pixels, &ret); + memcpy(&ie->content, &property.content, sizeof (Eina_Rectangle)); + ie->stretch.horizontal.region = property.stretch.horizontal.region; + ie->stretch.vertical.region = property.stretch.vertical.region; + } + else + { + evas_image_load_func->file_data(ie->loader_data, &property, pixels, &ret); + } - ie->flags.alpha_sparse = property.alpha_sparse; + ie->flags.alpha_sparse = property.info.alpha_sparse; - if (property.premul) evas_common_image_premul(ie); + if (property.info.premul) evas_common_image_premul(ie); return ret; } diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index 825d83ab77..59eb800724 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -598,6 +598,7 @@ struct _Image_Entry unsigned char need_unload : 1; unsigned char load_failed : 1; + unsigned char need_data : 1; struct { @@ -633,6 +634,14 @@ struct _Image_Entry int connect_num; int channel; Evas_Load_Error load_error; + + struct { + struct { + uint8_t *region; + } horizontal, vertical; + } stretch; + + Eina_Rectangle content; }; struct _Engine_Image_Entry diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index d6b53bc210..751f81cd07 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1354,6 +1354,8 @@ struct _Evas_Func Eina_Bool (*image_data_map) (void *engine, void **image, Eina_Rw_Slice *slice, int *stride, int x, int y, int w, int h, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode, int plane); Eina_Bool (*image_data_unmap) (void *engine, void *image, const Eina_Rw_Slice *slice); int (*image_data_maps_get) (void *engine, const void *image, const Eina_Rw_Slice **slices); + Eina_Bool (*image_content_region_get) (void *engine, void *image, Eina_Rectangle *content); + Eina_Bool (*image_stretch_region_get) (void *engine, void *image, uint8_t **horizontal, uint8_t **vertical); /* new api for direct data set (not put) */ void *(*image_data_slice_add) (void *engine, void *image, const Eina_Slice *slice, Eina_Bool copy, int w, int h, int stride, Evas_Colorspace space, int plane, Eina_Bool alpha); diff --git a/src/modules/ecore_imf/wayland/wayland_imcontext.c b/src/modules/ecore_imf/wayland/wayland_imcontext.c index d7bcfe7994..70781fb93e 100644 --- a/src/modules/ecore_imf/wayland/wayland_imcontext.c +++ b/src/modules/ecore_imf/wayland/wayland_imcontext.c @@ -299,7 +299,6 @@ text_input_commit_string(void *data, if (old_preedit) { - ecore_imf_context_preedit_end_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL); @@ -331,7 +330,6 @@ text_input_commit_string(void *data, if (surrounding) free(surrounding); - ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev); } } @@ -341,7 +339,6 @@ text_input_commit_string(void *data, imcontext->pending_commit.cursor = 0; imcontext->pending_commit.anchor = 0; - ecore_imf_context_commit_event_add(imcontext->ctx, text); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text); } @@ -354,17 +351,13 @@ commit_preedit(WaylandIMContext *imcontext) if (!imcontext->ctx) return; - ecore_imf_context_preedit_changed_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL); - ecore_imf_context_preedit_end_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL); - ecore_imf_context_commit_event_add(imcontext->ctx, - imcontext->preedit_commit); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)imcontext->preedit_commit); @@ -458,20 +451,17 @@ text_input_preedit_string(void *data, if (!old_preedit) { - ecore_imf_context_preedit_start_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL); } - ecore_imf_context_preedit_changed_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL); if (imcontext->preedit_text && strlen(imcontext->preedit_text) == 0) { - ecore_imf_context_preedit_end_event_add(imcontext->ctx); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL); @@ -492,7 +482,6 @@ text_input_delete_surrounding_text(void *data, imcontext->pending_commit.delete_index = ev.offset = index; imcontext->pending_commit.delete_length = ev.n_chars = length; - ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars); ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev); } diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index 6ae8224e47..59391c4f6e 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -1050,6 +1050,48 @@ eng_image_file_colorspace_get(void *data EINA_UNUSED, void *image) return im->cache_entry.space; } +static Eina_Bool +eng_image_content_region_get(void *engine EINA_UNUSED, void *image, Eina_Rectangle *content) +{ + RGBA_Image *im = image; + + if (!im) return EINA_FALSE; + + if (!im->cache_entry.need_data) return EINA_FALSE; + + if (!im->image.data) evas_cache_image_load_data(&im->cache_entry); + + if (!im->cache_entry.content.w || + !im->cache_entry.content.h) + return EINA_FALSE; + + if (!content) return EINA_FALSE; + + memcpy(content, &im->cache_entry.content, sizeof (Eina_Rectangle)); + return EINA_TRUE; +} + +static Eina_Bool +eng_image_stretch_region_get(void *engine EINA_UNUSED, void *image, + uint8_t **horizontal, uint8_t **vertical) +{ + RGBA_Image *im = image; + + if (!im) return EINA_FALSE; + + if (!im->cache_entry.need_data) return EINA_FALSE; + + if (!im->image.data) evas_cache_image_load_data(&im->cache_entry); + + if (!im->cache_entry.stretch.horizontal.region || + !im->cache_entry.stretch.vertical.region) + return EINA_FALSE; + + *horizontal = im->cache_entry.stretch.horizontal.region; + *vertical = im->cache_entry.stretch.vertical.region; + return EINA_TRUE; +} + static Eina_Bool eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane, Eina_Slice *slice, Evas_Colorspace *cspace, @@ -4611,6 +4653,8 @@ static Evas_Func func = eng_image_data_map, eng_image_data_unmap, eng_image_data_maps_get, + eng_image_content_region_get, + eng_image_stretch_region_get, eng_image_data_slice_add, eng_image_prepare, eng_image_surface_noscale_new, diff --git a/src/modules/evas/image_loaders/bmp/evas_image_load_bmp.c b/src/modules/evas/image_loaders/bmp/evas_image_load_bmp.c index 43dac5b06c..844b9d8f08 100644 --- a/src/modules/evas/image_loaders/bmp/evas_image_load_bmp.c +++ b/src/modules/evas/image_loaders/bmp/evas_image_load_bmp.c @@ -319,7 +319,7 @@ evas_image_load_file_close_bmp(void *loader_data) static Eina_Bool evas_image_load_file_head_bmp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader; @@ -454,7 +454,7 @@ evas_image_load_file_head_bmp(void *loader_data, static Eina_Bool evas_image_load_file_data_bmp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -1429,10 +1429,12 @@ evas_image_load_file_data_bmp(void *loader_data, static Evas_Image_Load_Func evas_image_load_bmp_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_bmp, evas_image_load_file_close_bmp, - evas_image_load_file_head_bmp, - evas_image_load_file_data_bmp, + (void*) evas_image_load_file_head_bmp, + NULL, + (void*) evas_image_load_file_data_bmp, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/dds/evas_image_load_dds.c b/src/modules/evas/image_loaders/dds/evas_image_load_dds.c index f3b133c7c9..e77c3e960b 100644 --- a/src/modules/evas/image_loaders/dds/evas_image_load_dds.c +++ b/src/modules/evas/image_loaders/dds/evas_image_load_dds.c @@ -161,7 +161,7 @@ _dword_read(const char **m) static Eina_Bool evas_image_load_file_head_dds(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { static const unsigned int base_flags = /* 0x1007 */ @@ -313,7 +313,7 @@ on_error: } static Eina_Bool -_dds_data_load(Evas_Loader_Internal *loader, Evas_Image_Property *prop, +_dds_data_load(Evas_Loader_Internal *loader, Emile_Image_Property *prop, unsigned char *map, void *pixels, int *error) { const unsigned char *src; @@ -442,7 +442,7 @@ on_error: Eina_Bool evas_image_load_file_data_dds(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -529,10 +529,12 @@ on_error: Evas_Image_Load_Func evas_image_load_dds_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_dds, evas_image_load_file_close_dds, - evas_image_load_file_head_dds, - evas_image_load_file_data_dds, + (void*) evas_image_load_file_head_dds, + NULL, + (void*) evas_image_load_file_data_dds, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/eet/evas_image_load_eet.c b/src/modules/evas/image_loaders/eet/evas_image_load_eet.c index 9ff212f8eb..4760ecc94e 100644 --- a/src/modules/evas/image_loaders/eet/evas_image_load_eet.c +++ b/src/modules/evas/image_loaders/eet/evas_image_load_eet.c @@ -95,7 +95,7 @@ static const Evas_Colorspace cspaces_etc2_rgba[] = { static Eina_Bool evas_image_load_file_head_eet(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -163,7 +163,7 @@ evas_image_load_file_head_eet(void *loader_data, Eina_Bool evas_image_load_file_data_eet(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -224,10 +224,12 @@ evas_image_load_file_data_eet(void *loader_data, Evas_Image_Load_Func evas_image_load_eet_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_eet, evas_image_load_file_close_eet, - evas_image_load_file_head_eet, - evas_image_load_file_data_eet, + (void*) evas_image_load_file_head_eet, + NULL, + (void*) evas_image_load_file_data_eet, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/generic/evas_image_load_generic.c b/src/modules/evas/image_loaders/generic/evas_image_load_generic.c index ec4917ffc0..7d0c8e3609 100644 --- a/src/modules/evas/image_loaders/generic/evas_image_load_generic.c +++ b/src/modules/evas/image_loaders/generic/evas_image_load_generic.c @@ -101,7 +101,7 @@ dotcat(char *dest, const char *src) static Eina_Bool _load(Eina_File *ef, const char *key, - Evas_Image_Property *prop, + Emile_Image_Property *prop, Evas_Image_Load_Opts *opts, void *pixels, int *error, Eina_Bool get_data) @@ -422,7 +422,7 @@ evas_image_load_file_close_generic(void *loader_data) static Eina_Bool evas_image_load_file_head_generic(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -432,7 +432,7 @@ evas_image_load_file_head_generic(void *loader_data, static Eina_Bool evas_image_load_file_data_generic(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -443,10 +443,12 @@ evas_image_load_file_data_generic(void *loader_data, Evas_Image_Load_Func evas_image_load_generic_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_generic, evas_image_load_file_close_generic, - evas_image_load_file_head_generic, - evas_image_load_file_data_generic, + (void*) evas_image_load_file_head_generic, + NULL, + (void*) evas_image_load_file_data_generic, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/gif/evas_image_load_gif.c b/src/modules/evas/image_loaders/gif/evas_image_load_gif.c index 737e3fb7be..308f909c86 100644 --- a/src/modules/evas/image_loaders/gif/evas_image_load_gif.c +++ b/src/modules/evas/image_loaders/gif/evas_image_load_gif.c @@ -399,7 +399,7 @@ _file_read(GifFileType *gft, GifByteType *buf, int len) static Eina_Bool evas_image_load_file_head_gif2(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Loader_Info *loader = loader_data; @@ -569,7 +569,7 @@ on_error: // jump here on any errors to clean up static Eina_Bool evas_image_load_file_data_gif2(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -905,10 +905,12 @@ evas_image_load_file_close_gif2(void *loader_data) // general module delcaration stuff static Evas_Image_Load_Func evas_image_load_gif_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_gif2, evas_image_load_file_close_gif2, - evas_image_load_file_head_gif2, - evas_image_load_file_data_gif2, + (void*) evas_image_load_file_head_gif2, + NULL, + (void*) evas_image_load_file_data_gif2, evas_image_load_frame_duration_gif2, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/ico/evas_image_load_ico.c b/src/modules/evas/image_loaders/ico/evas_image_load_ico.c index 520ef06aa8..fea7877502 100644 --- a/src/modules/evas/image_loaders/ico/evas_image_load_ico.c +++ b/src/modules/evas/image_loaders/ico/evas_image_load_ico.c @@ -111,7 +111,7 @@ evas_image_load_file_close_ico(void *loader_data) static Eina_Bool evas_image_load_file_head_ico(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -340,7 +340,7 @@ evas_image_load_file_head_ico(void *loader_data, static Eina_Bool evas_image_load_file_data_ico(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -792,10 +792,12 @@ evas_image_load_file_data_ico(void *loader_data, static Evas_Image_Load_Func evas_image_load_ico_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_ico, evas_image_load_file_close_ico, - evas_image_load_file_head_ico, - evas_image_load_file_data_ico, + (void*) evas_image_load_file_head_ico, + NULL, + (void*) evas_image_load_file_data_ico, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c b/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c index dd9af05acf..bf39927a49 100644 --- a/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c +++ b/src/modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c @@ -403,7 +403,7 @@ evas_image_load_file_close_jp2k(void *loader_data) static Eina_Bool evas_image_load_file_head_jp2k(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -432,7 +432,7 @@ evas_image_load_file_head_jp2k(void *loader_data, static Eina_Bool evas_image_load_file_data_jp2k(void *loader_data, - Evas_Image_Property *prop EINA_UNUSED, + Emile_Image_Property *prop EINA_UNUSED, void *pixels, int *error) { @@ -462,10 +462,12 @@ evas_image_load_file_data_jp2k(void *loader_data, static Evas_Image_Load_Func evas_image_load_jp2k_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_jp2k, evas_image_load_file_close_jp2k, - evas_image_load_file_head_jp2k, - evas_image_load_file_data_jp2k, + (void*) evas_image_load_file_head_jp2k, + NULL, + (void*) evas_image_load_file_data_jp2k, NULL, EINA_TRUE, EINA_TRUE diff --git a/src/modules/evas/image_loaders/jpeg/evas_image_load_jpeg.c b/src/modules/evas/image_loaders/jpeg/evas_image_load_jpeg.c index c80416aea0..1cb55c0de4 100644 --- a/src/modules/evas/image_loaders/jpeg/evas_image_load_jpeg.c +++ b/src/modules/evas/image_loaders/jpeg/evas_image_load_jpeg.c @@ -70,7 +70,7 @@ evas_image_load_file_close_jpeg(void *loader_data) static Eina_Bool evas_image_load_file_head_jpeg(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -95,7 +95,7 @@ _evas_image_load_jpeg_cancelled(void *data EINA_UNUSED, Eina_Bool evas_image_load_file_data_jpeg(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -116,10 +116,12 @@ evas_image_load_file_data_jpeg(void *loader_data, Evas_Image_Load_Func evas_image_load_jpeg_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_jpeg, evas_image_load_file_close_jpeg, - evas_image_load_file_head_jpeg, - evas_image_load_file_data_jpeg, + (void*) evas_image_load_file_head_jpeg, + NULL, + (void*) evas_image_load_file_data_jpeg, NULL, EINA_TRUE, EINA_TRUE diff --git a/src/modules/evas/image_loaders/pmaps/evas_image_load_pmaps.c b/src/modules/evas/image_loaders/pmaps/evas_image_load_pmaps.c index b9c383c90b..a541e4dcb6 100644 --- a/src/modules/evas/image_loaders/pmaps/evas_image_load_pmaps.c +++ b/src/modules/evas/image_loaders/pmaps/evas_image_load_pmaps.c @@ -67,7 +67,7 @@ evas_image_load_file_close_pmaps(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_pmaps(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -95,7 +95,7 @@ evas_image_load_file_head_pmaps(void *loader_data, static Eina_Bool evas_image_load_file_data_pmaps(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -551,10 +551,12 @@ pmaps_buffer_plain_bw_get(Pmaps_Buffer *b, DATA32 *val) /* external functions */ Evas_Image_Load_Func evas_image_load_pmaps_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_pmaps, evas_image_load_file_close_pmaps, - evas_image_load_file_head_pmaps, - evas_image_load_file_data_pmaps, + (void*) evas_image_load_file_head_pmaps, + NULL, + (void*) evas_image_load_file_data_pmaps, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/png/evas_image_load_png.c b/src/modules/evas/image_loaders/png/evas_image_load_png.c index 087c908b63..4ffd5643c6 100644 --- a/src/modules/evas/image_loaders/png/evas_image_load_png.c +++ b/src/modules/evas/image_loaders/png/evas_image_load_png.c @@ -10,6 +10,8 @@ #include "evas_private.h" #define PNG_BYTES_TO_CHECK 4 +#define WHITE 0xFFFFFFFF +#define BLACK 0xFF000000 typedef struct _Evas_PNG_Info Evas_PNG_Info; struct _Evas_PNG_Info @@ -17,6 +19,13 @@ struct _Evas_PNG_Info unsigned char *map; size_t length; size_t position; + + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 w32, h32; + int bit_depth, color_type, interlace_type; + + volatile Eina_Bool hasa; }; typedef struct _Evas_Loader_Internal Evas_Loader_Internal; @@ -36,6 +45,34 @@ static const Evas_Colorspace cspace_grey_alpha[2] = { EVAS_COLORSPACE_ARGB8888 }; +static void +_evas_image_png_update_x_content(Eina_Rectangle *r, int index) +{ + if (r->x == 0) + { + r->x = index; + r->w = 1; + } + else + { + r->w = index - r->x; + } +} + +static void +_evas_image_png_update_y_content(Eina_Rectangle *r, int index) +{ + if (r->y == 0) + { + r->y = index; + r->h = 1; + } + else + { + r->h = index - r->y; + } +} + static void _evas_image_png_read(png_structp png_ptr, png_bytep out, png_size_t count) { @@ -76,77 +113,65 @@ evas_image_load_file_close_png(void *loader_data) } static Eina_Bool -evas_image_load_file_head_png(void *loader_data, - Evas_Image_Property *prop, - int *error) +_evas_image_load_file_internal_head_png(Evas_Loader_Internal *loader, + Evas_Image_Property *prop, + Evas_PNG_Info *epi, + int *error, Eina_Bool close_file) { - Evas_Loader_Internal *loader = loader_data; - Evas_Image_Load_Opts *opts; - Eina_File *f; - - Evas_PNG_Info epi; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; - png_uint_32 w32, h32; - int bit_depth, color_type, interlace_type; - volatile char hasa; + Evas_Image_Load_Opts *opts = loader->opts; + Eina_File *f = loader->f; volatile Eina_Bool r = EINA_FALSE; - opts = loader->opts; - f = loader->f; + *error = EVAS_LOAD_ERROR_NONE; - hasa = 0; - epi.map = eina_file_map_all(f, EINA_FILE_RANDOM); - if (!epi.map) + epi->hasa = 0; + epi->map = eina_file_map_all(f, EINA_FILE_RANDOM); + if (!epi->map) { *error = EVAS_LOAD_ERROR_CORRUPT_FILE; goto close_file; } - epi.length = eina_file_size_get(f); - epi.position = 0; + epi->length = eina_file_size_get(f); + epi->position = 0; - if (epi.length < PNG_BYTES_TO_CHECK) + if (epi->length < PNG_BYTES_TO_CHECK) { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - goto close_file; + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + if (png_sig_cmp(epi->map, 0, PNG_BYTES_TO_CHECK)) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + epi->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!epi->png_ptr) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + epi->info_ptr = png_create_info_struct(epi->png_ptr); + if (!epi->info_ptr) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + png_set_read_fn(epi->png_ptr, epi, _evas_image_png_read); + if (setjmp(png_jmpbuf(epi->png_ptr))) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto close_file; } - if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK)) + png_read_info(epi->png_ptr, epi->info_ptr); + png_get_IHDR(epi->png_ptr, epi->info_ptr, (png_uint_32 *) (&epi->w32), + (png_uint_32 *) (&epi->h32), &epi->bit_depth, &epi->color_type, + &epi->interlace_type, NULL, NULL); + if ((epi->w32 < 1) || (epi->h32 < 1) || + (epi->w32 > IMG_MAX_SIZE) || (epi->h32 > IMG_MAX_SIZE) || + IMG_TOO_BIG(epi->w32, epi->h32)) { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - goto close_file; - } - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - png_set_read_fn(png_ptr, &epi, _evas_image_png_read); - - if (setjmp(png_jmpbuf(png_ptr))) - { - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - goto close_file; - } - - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32), - (png_uint_32 *) (&h32), &bit_depth, &color_type, - &interlace_type, NULL, NULL); - if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) || - IMG_TOO_BIG(w32, h32)) - { - if (IMG_TOO_BIG(w32, h32)) + if (IMG_TOO_BIG(epi->w32, epi->h32)) *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; else *error = EVAS_LOAD_ERROR_GENERIC; @@ -155,28 +180,28 @@ evas_image_load_file_head_png(void *loader_data, if (opts->emile.region.w > 0 && opts->emile.region.h > 0) { - if (((int) w32 < opts->emile.region.x + opts->emile.region.w) || - ((int) h32 < opts->emile.region.y + opts->emile.region.h)) + if (((int) epi->w32 < opts->emile.region.x + opts->emile.region.w) || + ((int) epi->h32 < opts->emile.region.y + opts->emile.region.h)) { *error = EVAS_LOAD_ERROR_GENERIC; goto close_file; } if(opts->emile.scale_down_by > 1) { - prop->w = opts->emile.region.w / opts->emile.scale_down_by; - prop->h = opts->emile.region.h / opts->emile.scale_down_by; + prop->info.w = opts->emile.region.w / opts->emile.scale_down_by; + prop->info.h = opts->emile.region.h / opts->emile.scale_down_by; } else { - prop->w = opts->emile.region.w; - prop->h = opts->emile.region.h; + prop->info.w = opts->emile.region.w; + prop->info.h = opts->emile.region.h; } } else if (opts->emile.scale_down_by > 1) { - prop->w = (int) w32 / opts->emile.scale_down_by; - prop->h = (int) h32 / opts->emile.scale_down_by; - if ((prop->w < 1) || (prop->h < 1)) + prop->info.w = (int) epi->w32 / opts->emile.scale_down_by; + prop->info.h = (int) epi->h32 / opts->emile.scale_down_by; + if ((prop->info.w < 1) || (prop->info.h < 1)) { *error = EVAS_LOAD_ERROR_GENERIC; goto close_file; @@ -184,34 +209,365 @@ evas_image_load_file_head_png(void *loader_data, } else { - prop->w = (int) w32; - prop->h = (int) h32; + prop->info.w = (int) epi->w32; + prop->info.h = (int) epi->h32; } - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) hasa = 1; - switch (color_type) + if (png_get_valid(epi->png_ptr, epi->info_ptr, PNG_INFO_tRNS)) epi->hasa = 1; + switch (epi->color_type) { case PNG_COLOR_TYPE_RGB_ALPHA: - hasa = 1; + epi->hasa = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: - hasa = 1; - prop->cspaces = cspace_grey_alpha; + epi->hasa = 1; + prop->info.cspaces = cspace_grey_alpha; break; case PNG_COLOR_TYPE_GRAY: - if (!hasa) prop->cspaces = cspace_grey; + if (!epi->hasa) prop->info.cspaces = cspace_grey; break; } - if (hasa) prop->alpha = 1; + if (epi->hasa) prop->info.alpha = 1; + + prop->need_data = eina_str_has_extension(eina_file_filename_get(f), ".9.png"); + if (prop->need_data) + { + // Adjust size to take into account the 9 patch pixels information + prop->info.w -= 2; + prop->info.h -= 2; + } + + r = EINA_TRUE; + + if (!close_file) return r; + + close_file: + if (epi->png_ptr) png_destroy_read_struct(&epi->png_ptr, + epi->info_ptr ? &epi->info_ptr : NULL, + NULL); + if (epi->map) eina_file_map_free(f, epi->map); + memset(epi, 0, sizeof (Evas_PNG_Info)); + + return r; +} + +static Eina_Bool +evas_image_load_file_head_png(void *loader_data, + Evas_Image_Property *prop, + int *error) +{ + Evas_Loader_Internal *loader = loader_data; + Evas_PNG_Info epi; + + memset(&epi, 0, sizeof (Evas_PNG_Info)); + + if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_TRUE)) + return EINA_FALSE; + + return EINA_TRUE; +} + +static inline Eina_Bool +_is_black(DATA32 *ptr) +{ + if (*ptr == BLACK) return EINA_TRUE; + return EINA_FALSE; +} + +static Eina_Bool +evas_image_load_file_head_with_data_png(void *loader_data, + Evas_Image_Property *prop, + void *pixels, + int *error) +{ + Evas_Loader_Internal *loader = loader_data; + Evas_Image_Load_Opts *opts; + Eina_File *f; + + unsigned char *src_ptr; + unsigned char *pixels2; + unsigned char *surface; + Evas_PNG_Info epi; + Eina_Rectangle region; + unsigned int pack_offset; + int w, h; + char passes; + int i, j, p, k; + volatile int scale_ratio = 1; + int image_w = 0, image_h = 0; + volatile Eina_Bool r = EINA_FALSE; + Eina_Bool nine_patch = EINA_FALSE; + + opts = loader->opts; + f = loader->f; + + memset(&epi, 0, sizeof (Evas_PNG_Info)); + region = opts->emile.region; + + if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE)) + return EINA_FALSE; + + image_w = epi.w32; + image_h = epi.h32; + + // We are leveragging region code to not load the border information pixels + // from 9patch files into the surface used by Evas + if (prop->need_data) + { + nine_patch = EINA_TRUE; + + region.x += 1; + region.y += 1; + + if (region.w > 0 && region.h > 0) + { + if (region.x + region.w + 1 < image_w) region.w += 1; + else region.w = image_w - region.x - 1; + if (region.y + region.h + 1 < image_h) region.h += 1; + else region.h = image_h - region.y - 1; + } + else + { + region.w = image_w - region.x - 1; + region.h = image_h - region.y - 1; + } + } + + surface = pixels; + + /* Prep for transformations... ultimately we want ARGB */ + /* expand palette -> RGB if necessary */ + if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr); + /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */ + if ((epi.color_type == PNG_COLOR_TYPE_GRAY) || + (epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + { + if (prop->info.cspace == EVAS_COLORSPACE_ARGB8888) + png_set_gray_to_rgb(epi.png_ptr); + if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr); + } + /* reduce 16bit color -> 8bit color if necessary */ + if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr); + /* pack all pixels to byte boundaries */ + png_set_packing(epi.png_ptr); + + w = prop->info.w; + h = prop->info.h; + + switch (prop->info.cspace) + { + case EVAS_COLORSPACE_ARGB8888: + /* we want ARGB */ +#ifdef WORDS_BIGENDIAN + png_set_swap_alpha(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE); +#else + png_set_bgr(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER); +#endif + pack_offset = sizeof(DATA32); + break; + case EVAS_COLORSPACE_AGRY88: + /* we want AGRY */ +#ifdef WORDS_BIGENDIAN + png_set_swap_alpha(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE); +#else + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER); +#endif + pack_offset = sizeof(DATA16); + break; + case EVAS_COLORSPACE_GRY8: pack_offset = sizeof(DATA8); break; + default: abort(); + } + + passes = png_set_interlace_handling(epi.png_ptr); + + /* we read image line by line in all case because of .9.png */ + pixels2 = malloc(image_w * image_h * pack_offset); + if (!pixels2) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + + for (p = 0; p < passes; p++) + { + for (i = 0; i < image_h; i++) + png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL); + } + png_read_end(epi.png_ptr, epi.info_ptr); + + if (nine_patch && pack_offset != sizeof (DATA32)) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto close_file; + } + + if (nine_patch) + { + DATA32 *src_ptr1; + DATA32 *src_ptr2; + Eina_Bool stretchable = EINA_FALSE; + Eina_Rectangle optional_content = { 0 }; + uint8_t current = 0; + + memset(&prop->content, 0, sizeof (Eina_Rectangle)); + + // Top line of the image + src_ptr1 = (DATA32*) pixels2 + 1; + // Bottom line of the image + src_ptr2 = src_ptr1 + (image_h - 1) * image_w; + + // Extract top stretch zone and horizontal content area + for (i = 1; i < image_w - 1; + i++, src_ptr1++, src_ptr2++) + { + Eina_Bool bp1 = _is_black(src_ptr1); + Eina_Bool bp2 = _is_black(src_ptr2); + + // Updating horizontal area where content can be located + if (bp2) + _evas_image_png_update_x_content(&prop->content, i); + + // In case no content area is provided, let's make it up + if (bp1) + _evas_image_png_update_x_content(&optional_content, i); + + // Switching from a non stretchable to a stretchable zone or the opposite + if (!((stretchable && (bp1)) || + (!stretchable && (!bp1)))) + { + evas_loader_helper_stretch_region_push(&prop->stretch.horizontal.region, + ¤t, stretchable); + stretchable = !stretchable; + } + + // Keep counting in the area we are in + current++; + + if (current != 0x7F) continue; + + // The bucket is full + evas_loader_helper_stretch_region_push(&prop->stretch.horizontal.region, + ¤t, stretchable); + } + + current = 0; + + // Left border of the image + src_ptr1 = (DATA32*) pixels2 + image_w; + // Right border of the image + src_ptr2 = src_ptr1 + (image_w - 1); + + for (i = 1; i < image_h - 1; + i++, src_ptr1 += image_w, src_ptr2 += image_w) + { + Eina_Bool bp1 = _is_black(src_ptr1); + Eina_Bool bp2 = _is_black(src_ptr2); + + // Updating vertical area where content can be located + if (bp2) + _evas_image_png_update_y_content(&prop->content, i); + + // In case no content area is provided, let's make it up + if (bp1) + _evas_image_png_update_y_content(&optional_content, i); + + // Switching from a non stretchable to a stretchable zone or the opposite + if (!((stretchable && (bp1)) || + (!stretchable && (!bp1)))) + { + evas_loader_helper_stretch_region_push(&prop->stretch.vertical.region, + ¤t, stretchable); + stretchable = !stretchable; + } + + // Keep counting in the area we are in + current++; + + if (current != 0x7F) continue; + + // The bucket is full + evas_loader_helper_stretch_region_push(&prop->stretch.vertical.region, + ¤t, stretchable); + } + + // Content zone is optional, if not provided, we should use the one we guessed + if (prop->content.x == 0 || prop->content.y == 0) + memcpy(&prop->content, &optional_content, sizeof (Eina_Rectangle)); + + // Check that the limit of our content zone are correct + // This could be handled as an incorrect file completly, + // but let's try to recover + if (prop->content.x == 0 || prop->content.y == 0) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto close_file; + } + if ((prop->content.x + prop->content.w >= image_w - 1) && + (prop->content.y + prop->content.h >= image_h - 1)) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + goto close_file; + } + + // Correct the work space to be the same as the image one for intersection + // with region and correct back afterward. + prop->content.x++; + prop->content.y++; + if (eina_rectangle_intersection(&prop->content, ®ion)) + { + prop->content.x--; + prop->content.y--; + } + } + + src_ptr = pixels2 + (region.y * image_w * pack_offset) + region.x * pack_offset; + + //general case: 4 bytes pixel. + if (pack_offset == sizeof(DATA32)) + { + DATA32 *dst_ptr = (DATA32 *) surface; + DATA32 *src_ptr2 = (DATA32 *) src_ptr; + + for (i = 0; i < h; i++) + { + for (j = 0; j < w; j++) + { + *dst_ptr = *src_ptr2; + ++dst_ptr; + src_ptr2 += scale_ratio; + } + src_ptr2 += scale_ratio * (image_w - w); + } + } + else + { + unsigned char *dst_ptr = surface; + + for (i = 0; i < h; i++) + { + for (j = 0; j < w; j++) + { + for (k = 0; k < (int)pack_offset; k++) + dst_ptr[k] = src_ptr[k + scale_ratio * j * pack_offset]; + dst_ptr += pack_offset; + } + src_ptr += scale_ratio * (image_w - w) * pack_offset; + } + } + free(pixels2); + + prop->info.premul = EINA_TRUE; *error = EVAS_LOAD_ERROR_NONE; r = EINA_TRUE; close_file: - if (png_ptr) png_destroy_read_struct(&png_ptr, - info_ptr ? &info_ptr : NULL, - NULL); - if (epi.map) eina_file_map_free(f, epi. map); - + if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr, + epi.info_ptr ? &epi.info_ptr : NULL, + NULL); + if (epi.map) eina_file_map_free(f, epi.map); return r; } @@ -226,14 +582,9 @@ evas_image_load_file_data_png(void *loader_data, Eina_File *f; unsigned char *surface; - png_structp png_ptr = NULL; - png_infop info_ptr = NULL; Evas_PNG_Info epi; - png_uint_32 w32, h32; unsigned int pack_offset; int w, h; - int bit_depth, color_type, interlace_type; - volatile char hasa; char passes; int i, j, p, k; volatile int scale_ratio = 1; @@ -244,131 +595,76 @@ evas_image_load_file_data_png(void *loader_data, opts = loader->opts; f = loader->f; - hasa = 0; + memset(&epi, 0, sizeof (Evas_PNG_Info)); - epi.map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL); - if (!epi.map) - { - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - goto close_file; - } - epi.length = eina_file_size_get(f); - epi.position = 0; + if (!_evas_image_load_file_internal_head_png(loader, prop, &epi, error, EINA_FALSE)) + return EINA_FALSE; - if (epi.length < PNG_BYTES_TO_CHECK) - { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - goto close_file; - } - - /* if we havent read the header before, set the header data */ - if (png_sig_cmp(epi.map, 0, PNG_BYTES_TO_CHECK)) - { - *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; - goto close_file; - } - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - { - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr, NULL, NULL); - *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; - goto close_file; - } - - png_set_read_fn(png_ptr, &epi, _evas_image_png_read); - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - *error = EVAS_LOAD_ERROR_CORRUPT_FILE; - goto close_file; - } - - png_read_info(png_ptr, info_ptr); - png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32), - (png_uint_32 *) (&h32), &bit_depth, &color_type, - &interlace_type, NULL, NULL); - image_w = w32; - image_h = h32; + image_w = epi.w32; + image_h = epi.h32; if (opts->emile.scale_down_by > 1) { scale_ratio = opts->emile.scale_down_by; - w32 /= scale_ratio; - h32 /= scale_ratio; + epi.w32 /= scale_ratio; + epi.h32 /= scale_ratio; } if ((opts->emile.region.w > 0 && opts->emile.region.h > 0) && (opts->emile.region.w != image_w || opts->emile.region.h != image_h)) { - w32 = opts->emile.region.w / scale_ratio; - h32 = opts->emile.region.h / scale_ratio; + epi.w32 = opts->emile.region.w / scale_ratio; + epi.h32 = opts->emile.region.h / scale_ratio; region_set = 1; } - if (prop->w != w32 || - prop->h != h32) + if (prop->info.w != epi.w32 || + prop->info.h != epi.h32) { - *error = EVAS_LOAD_ERROR_GENERIC; - goto close_file; + *error = EVAS_LOAD_ERROR_GENERIC; + goto close_file; } surface = pixels; - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - { - /* expand transparency entry -> alpha channel if present */ - png_set_tRNS_to_alpha(png_ptr); - hasa = 1; - } - if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) hasa = 1; - if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) hasa = 1; - if (hasa) prop->alpha = 1; /* Prep for transformations... ultimately we want ARGB */ /* expand palette -> RGB if necessary */ - if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); + if (epi.color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(epi.png_ptr); /* expand gray (w/reduced bits) -> 8-bit RGB if necessary */ - if ((color_type == PNG_COLOR_TYPE_GRAY) || - (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + if ((epi.color_type == PNG_COLOR_TYPE_GRAY) || + (epi.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { - if (prop->cspace == EVAS_COLORSPACE_ARGB8888) - png_set_gray_to_rgb(png_ptr); - if (bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + if (prop->info.cspace == EVAS_COLORSPACE_ARGB8888) + png_set_gray_to_rgb(epi.png_ptr); + if (epi.bit_depth < 8) png_set_expand_gray_1_2_4_to_8(epi.png_ptr); } /* reduce 16bit color -> 8bit color if necessary */ - if (bit_depth > 8) png_set_strip_16(png_ptr); + if (epi.bit_depth > 8) png_set_strip_16(epi.png_ptr); /* pack all pixels to byte boundaries */ - png_set_packing(png_ptr); + png_set_packing(epi.png_ptr); - w = w32; - h = h32; + w = epi.w32; + h = epi.h32; - switch (prop->cspace) + switch (prop->info.cspace) { case EVAS_COLORSPACE_ARGB8888: /* we want ARGB */ #ifdef WORDS_BIGENDIAN - png_set_swap_alpha(png_ptr); - if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); + png_set_swap_alpha(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE); #else - png_set_bgr(png_ptr); - if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + png_set_bgr(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER); #endif pack_offset = sizeof(DATA32); break; case EVAS_COLORSPACE_AGRY88: /* we want AGRY */ #ifdef WORDS_BIGENDIAN - png_set_swap_alpha(png_ptr); - if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); + png_set_swap_alpha(epi.png_ptr); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_BEFORE); #else - if (!hasa) png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + if (!epi.hasa) png_set_filler(epi.png_ptr, 0xff, PNG_FILLER_AFTER); #endif pack_offset = sizeof(DATA16); break; @@ -376,7 +672,7 @@ evas_image_load_file_data_png(void *loader_data, default: abort(); } - passes = png_set_interlace_handling(png_ptr); + passes = png_set_interlace_handling(epi.png_ptr); /* we read image line by line if scale down was set */ if (scale_ratio == 1 && region_set == 0) @@ -384,9 +680,9 @@ evas_image_load_file_data_png(void *loader_data, for (p = 0; p < passes; p++) { for (i = 0; i < h; i++) - png_read_row(png_ptr, surface + (i * w * pack_offset), NULL); + png_read_row(epi.png_ptr, surface + (i * w * pack_offset), NULL); } - png_read_end(png_ptr, info_ptr); + png_read_end(epi.png_ptr, epi.info_ptr); } else { @@ -409,9 +705,9 @@ evas_image_load_file_data_png(void *loader_data, unsigned short *pbuf; for (skip_row = 0; skip_row < region_y; skip_row++) - png_read_row(png_ptr, tmp_line, NULL); + png_read_row(epi.png_ptr, tmp_line, NULL); - png_read_row(png_ptr, tmp_line, NULL); + png_read_row(epi.png_ptr, tmp_line, NULL); src_ptr = tmp_line + (region_x * pack_offset); //The first pixel, of the first line @@ -450,7 +746,7 @@ evas_image_load_file_data_png(void *loader_data, //vertical interpolation. for (j = 0; j < scale_ratio; j++) { - png_read_row(png_ptr, tmp_line, NULL); + png_read_row(epi.png_ptr, tmp_line, NULL); src_ptr = tmp_line + (region_x * pack_offset); for (p = 0; p < line_size; ++p) @@ -486,7 +782,7 @@ evas_image_load_file_data_png(void *loader_data, } for (skip_row = region_y + h * scale_ratio; skip_row < image_h; skip_row++) - png_read_row(png_ptr, tmp_line, NULL); + png_read_row(epi.png_ptr, tmp_line, NULL); } else { @@ -499,8 +795,9 @@ evas_image_load_file_data_png(void *loader_data, for (p = 0; p < passes; p++) { for (i = 0; i < image_h; i++) - png_read_row(png_ptr, pixels2 + (i * image_w * pack_offset), NULL); + png_read_row(epi.png_ptr, pixels2 + (i * image_w * pack_offset), NULL); } + png_read_end(epi.png_ptr, epi.info_ptr); src_ptr = pixels2 + (region_y * image_w * pack_offset) + region_x * pack_offset; @@ -541,24 +838,26 @@ evas_image_load_file_data_png(void *loader_data, } } - prop->premul = EINA_TRUE; + prop->info.premul = EINA_TRUE; *error = EVAS_LOAD_ERROR_NONE; r = EINA_TRUE; close_file: - if (png_ptr) png_destroy_read_struct(&png_ptr, - info_ptr ? &info_ptr : NULL, - NULL); + if (epi.png_ptr) png_destroy_read_struct(&epi.png_ptr, + epi.info_ptr ? &epi.info_ptr : NULL, + NULL); if (epi.map) eina_file_map_free(f, epi.map); return r; } static Evas_Image_Load_Func evas_image_load_png_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_png, evas_image_load_file_close_png, evas_image_load_file_head_png, + evas_image_load_file_head_with_data_png, evas_image_load_file_data_png, NULL, EINA_TRUE, diff --git a/src/modules/evas/image_loaders/psd/evas_image_load_psd.c b/src/modules/evas/image_loaders/psd/evas_image_load_psd.c index d8f15b3dd9..c8abd1b893 100644 --- a/src/modules/evas/image_loaders/psd/evas_image_load_psd.c +++ b/src/modules/evas/image_loaders/psd/evas_image_load_psd.c @@ -147,7 +147,7 @@ evas_image_load_file_close_psd(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_psd(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -691,7 +691,7 @@ read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t le } Eina_Bool -read_psd_cmyk(Evas_Image_Property *prop, void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) +read_psd_cmyk(Emile_Image_Property *prop, void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) { unsigned int color_mode, resource_size, misc_info, size, j, data_size; unsigned short compressed; @@ -797,7 +797,7 @@ read_psd_cmyk(Evas_Image_Property *prop, void *pixels, PSD_Header *head, const u static Eina_Bool evas_image_load_file_data_psd(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -882,10 +882,12 @@ get_compressed_channels_length(PSD_Header *head, } static const Evas_Image_Load_Func evas_image_load_psd_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_psd, evas_image_load_file_close_psd, - evas_image_load_file_head_psd, - evas_image_load_file_data_psd, + (void*) evas_image_load_file_head_psd, + NULL, + (void*) evas_image_load_file_data_psd, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/tga/evas_image_load_tga.c b/src/modules/evas/image_loaders/tga/evas_image_load_tga.c index 344c363ed2..d8ef67fc59 100644 --- a/src/modules/evas/image_loaders/tga/evas_image_load_tga.c +++ b/src/modules/evas/image_loaders/tga/evas_image_load_tga.c @@ -68,7 +68,7 @@ evas_image_load_file_close_tga(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_tga(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -164,7 +164,7 @@ close_file: static Eina_Bool evas_image_load_file_data_tga(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -563,10 +563,12 @@ evas_image_load_file_data_tga(void *loader_data, static Evas_Image_Load_Func evas_image_load_tga_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_tga, evas_image_load_file_close_tga, - evas_image_load_file_head_tga, - evas_image_load_file_data_tga, + (void*) evas_image_load_file_head_tga, + NULL, + (void*) evas_image_load_file_data_tga, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c b/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c index 72da89af1e..ad90605e85 100644 --- a/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c +++ b/src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c @@ -70,7 +70,7 @@ evas_image_load_file_close_tgv(void *loader_data) static Eina_Bool evas_image_load_file_head_tgv(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Evas_Loader_Internal *loader = loader_data; @@ -87,7 +87,7 @@ evas_image_load_file_head_tgv(void *loader_data, Eina_Bool evas_image_load_file_data_tgv(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -105,10 +105,12 @@ evas_image_load_file_data_tgv(void *loader_data, Evas_Image_Load_Func evas_image_load_tgv_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_tgv, evas_image_load_file_close_tgv, - evas_image_load_file_head_tgv, - evas_image_load_file_data_tgv, + (void*) evas_image_load_file_head_tgv, + NULL, + (void*) evas_image_load_file_data_tgv, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/tiff/evas_image_load_tiff.c b/src/modules/evas/image_loaders/tiff/evas_image_load_tiff.c index e07206b51e..6f1cf61e14 100644 --- a/src/modules/evas/image_loaders/tiff/evas_image_load_tiff.c +++ b/src/modules/evas/image_loaders/tiff/evas_image_load_tiff.c @@ -103,7 +103,7 @@ evas_image_load_file_close_tiff(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_tiff(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -186,7 +186,7 @@ evas_image_load_file_head_tiff(void *loader_data, static Eina_Bool evas_image_load_file_data_tiff(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -332,10 +332,12 @@ evas_image_load_file_data_tiff(void *loader_data, static Evas_Image_Load_Func evas_image_load_tiff_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_tiff, evas_image_load_file_close_tiff, - evas_image_load_file_head_tiff, - evas_image_load_file_data_tiff, + (void*) evas_image_load_file_head_tiff, + NULL, + (void*) evas_image_load_file_data_tiff, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/wbmp/evas_image_load_wbmp.c b/src/modules/evas/image_loaders/wbmp/evas_image_load_wbmp.c index af539a041b..b601901d49 100644 --- a/src/modules/evas/image_loaders/wbmp/evas_image_load_wbmp.c +++ b/src/modules/evas/image_loaders/wbmp/evas_image_load_wbmp.c @@ -41,7 +41,7 @@ evas_image_load_file_close_wbmp(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_wbmp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -98,7 +98,7 @@ evas_image_load_file_head_wbmp(void *loader_data, static Eina_Bool evas_image_load_file_data_wbmp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -181,10 +181,12 @@ evas_image_load_file_data_wbmp(void *loader_data, static Evas_Image_Load_Func evas_image_load_wbmp_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_wbmp, evas_image_load_file_close_wbmp, - evas_image_load_file_head_wbmp, - evas_image_load_file_data_wbmp, + (void*) evas_image_load_file_head_wbmp, + NULL, + (void*) evas_image_load_file_data_wbmp, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/webp/evas_image_load_webp.c b/src/modules/evas/image_loaders/webp/evas_image_load_webp.c index e3f97bb77a..bd082455a2 100644 --- a/src/modules/evas/image_loaders/webp/evas_image_load_webp.c +++ b/src/modules/evas/image_loaders/webp/evas_image_load_webp.c @@ -52,7 +52,7 @@ evas_image_load_file_close_webp(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_webp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -73,7 +73,7 @@ evas_image_load_file_head_webp(void *loader_data, static Eina_Bool evas_image_load_file_data_webp(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -112,10 +112,12 @@ evas_image_load_file_data_webp(void *loader_data, static Evas_Image_Load_Func evas_image_load_webp_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_webp, evas_image_load_file_close_webp, - evas_image_load_file_head_webp, - evas_image_load_file_data_webp, + (void*) evas_image_load_file_head_webp, + NULL, + (void*) evas_image_load_file_data_webp, NULL, EINA_TRUE, EINA_FALSE diff --git a/src/modules/evas/image_loaders/xpm/evas_image_load_xpm.c b/src/modules/evas/image_loaders/xpm/evas_image_load_xpm.c index 4bf08b5a8d..d7aa25ded3 100644 --- a/src/modules/evas/image_loaders/xpm/evas_image_load_xpm.c +++ b/src/modules/evas/image_loaders/xpm/evas_image_load_xpm.c @@ -1688,7 +1688,7 @@ _cmap_cmp_key_cb(const Eina_Rbtree *node, const void *key, int length EINA_UNUSE /** FIXME: clean this up and make more efficient **/ static Eina_Bool -evas_image_load_file_xpm(Eina_File *f, Evas_Image_Property *prop, void *pixels, int load_data, int *error) +evas_image_load_file_xpm(Eina_File *f, Emile_Image_Property *prop, void *pixels, int load_data, int *error) { DATA32 *ptr, *end, *head = NULL; const char *map = NULL; @@ -2193,7 +2193,7 @@ evas_image_load_file_close_xpm(void *loader_data EINA_UNUSED) static Eina_Bool evas_image_load_file_head_xpm(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, int *error) { Eina_File *f = loader_data; @@ -2203,7 +2203,7 @@ evas_image_load_file_head_xpm(void *loader_data, static Eina_Bool evas_image_load_file_data_xpm(void *loader_data, - Evas_Image_Property *prop, + Emile_Image_Property *prop, void *pixels, int *error) { @@ -2214,10 +2214,12 @@ evas_image_load_file_data_xpm(void *loader_data, static Evas_Image_Load_Func evas_image_load_xpm_func = { + EVAS_IMAGE_LOAD_VERSION, evas_image_load_file_open_xpm, evas_image_load_file_close_xpm, - evas_image_load_file_head_xpm, - evas_image_load_file_data_xpm, + (void*) evas_image_load_file_head_xpm, + NULL, + (void*) evas_image_load_file_data_xpm, NULL, EINA_FALSE, EINA_FALSE diff --git a/src/static_libs/draw/meson.build b/src/static_libs/draw/meson.build index 32fe35e989..0e7dce9cdd 100644 --- a/src/static_libs/draw/meson.build +++ b/src/static_libs/draw/meson.build @@ -9,7 +9,7 @@ draw_src = [ draw_opt_lib = [ ] -if cpu_sse3 == true and sys_windows == false +if cpu_sse3 == true draw_opt = static_library('draw_opt', sources: [ 'draw_main_sse2.c' ], include_directories: config_dir + [include_directories(join_paths('..', '..', 'lib'))], diff --git a/src/tests/ecore_cxx/ecore_cxx_test_safe_call.cc b/src/tests/ecore_cxx/ecore_cxx_test_safe_call.cc index 5ad5da5015..749b8b0fda 100644 --- a/src/tests/ecore_cxx/ecore_cxx_test_safe_call.cc +++ b/src/tests/ecore_cxx/ecore_cxx_test_safe_call.cc @@ -14,7 +14,7 @@ void call_async(efl::eina::mutex& mutex, efl::eina::condition_variable& cond, in { efl::ecore::main_loop_thread_safe_call_async ( - [&mutex,&cond,&done] + [&mutex,&done] { std::cout << "yeah" << std::endl; efl::eina::unique_lock l(mutex); diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index be66f0842c..aa3565dd76 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -120,7 +120,7 @@ class TestEoInherit public static void inherited_collected() { var wref = CreateCollectableInherited(); - Test.CollectAndIterate(); + Test.CollectAndIterate(300, 10); Test.AssertNull(wref.Target); } diff --git a/src/tests/efl_mono/FunctionPointers.cs b/src/tests/efl_mono/FunctionPointers.cs index 4536704389..911e20ea38 100644 --- a/src/tests/efl_mono/FunctionPointers.cs +++ b/src/tests/efl_mono/FunctionPointers.cs @@ -171,9 +171,7 @@ class TestFunctionPointers // Should release the handle to the wrapper allocated when calling set_callback from C. obj.SetCallback(twice); - GC.Collect(); - GC.WaitForPendingFinalizers(); - Efl.App.AppMain.Iterate(); + Test.CollectAndIterate(300, 10); Test.Assert(obj.set_called, "set_callback override must have been called"); Test.Assert(!obj.invoke_called, "invoke_callback must not have been called"); diff --git a/src/tests/efl_mono/TestUtils.cs b/src/tests/efl_mono/TestUtils.cs index 21b8ec7794..bbc37b5e65 100644 --- a/src/tests/efl_mono/TestUtils.cs +++ b/src/tests/efl_mono/TestUtils.cs @@ -200,14 +200,17 @@ public static class Test /// Runs a number of garbage collections and iterate the main loop. /// The iteration is needed to make sure objects collected in the GC thread /// are efl_unref'd in the main thread. - public static void CollectAndIterate(int iterations=1000) + public static void CollectAndIterate(int iterations=1000, int global_iterations=1) { - for (int i = 0; i < iterations; i++) + for (int g = 0; g < global_iterations; ++g) { - System.GC.Collect(); + for (int i = 0; i < iterations; ++i) + { + System.GC.Collect(); + } + System.GC.WaitForPendingFinalizers(); + Efl.App.AppMain.Iterate(); } - System.GC.WaitForPendingFinalizers(); - Efl.App.AppMain.Iterate(); } } diff --git a/src/tests/efl_mono/Value.cs b/src/tests/efl_mono/Value.cs index 75b8e96ca1..ba56c36409 100644 --- a/src/tests/efl_mono/Value.cs +++ b/src/tests/efl_mono/Value.cs @@ -3,7 +3,9 @@ #pragma warning disable 1591 using System; +using System.Linq; using System.Diagnostics.CodeAnalysis; +using System.Collections.Generic; namespace TestSuite { @@ -1029,5 +1031,151 @@ public static class TestEinaValue { /* Test.Assert(false, "Implement me."); */ /* } */ } + +public static class TestValueFromObject +{ + + private class Holder + { + public int Number { get; set; } + public double Factor { get; set; } + public string Name { get; set; } + public Efl.Object Obj { get; set; } + } + + public static void TestConversionFromToObject() + { + var source = new Holder { + Number = 1984, + Factor = 3.14, + Name = "Orwell", + Obj = new Dummy.TestObject(), + }; + + { + var prop = source.GetType().GetProperty("Name"); + var v = new Eina.Value(prop.GetValue(source)); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.String); + Test.AssertEquals((string)v, prop.GetValue(source)); + + Test.Assert(v.Set("New value")); + prop.SetValue(source, v.Unwrap()); + Test.AssertEquals(prop.GetValue(source), "New value"); + } + + { + var prop = source.GetType().GetProperty("Factor"); + var v = new Eina.Value(prop.GetValue(source)); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Double); + Test.AssertAlmostEquals((double)v, (double)prop.GetValue(source)); + + Test.Assert(v.Set(2.78)); + prop.SetValue(source, v.Unwrap()); + Test.AssertEquals(prop.GetValue(source), 2.78); + } + + { + var prop = source.GetType().GetProperty("Number"); + var v = new Eina.Value(prop.GetValue(source)); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Int32); + Test.AssertEquals((int)v, prop.GetValue(source)); + + Test.Assert(v.Set(2012)); + prop.SetValue(source, v.Unwrap()); + Test.AssertEquals(prop.GetValue(source), 2012); + } + + { + var prop = source.GetType().GetProperty("Obj"); + var v = new Eina.Value(prop.GetValue(source)); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Object); + Test.AssertEquals((Efl.Object)v, prop.GetValue(source)); + + var newObj = new Dummy.TestObject(); + Test.Assert(v.Set(newObj)); + prop.SetValue(source, v.Unwrap()); + Test.AssertEquals(prop.GetValue(source), newObj); + } + } + + private class ComplexHolder + { + public IEnumerable Bag { get; set; } + public IEnumerable BagOfObjects { get; set; } + } + + public static void TestContainerFromToObject() + { + var initialBag = new Eina.Array(); + initialBag.Push(2); + initialBag.Push(4); + initialBag.Push(6); + + var source = new ComplexHolder { Bag = initialBag }; + var prop = source.GetType().GetProperty("Bag"); + var v = new Eina.Value(prop.GetValue(source)); + Test.AssertEquals(prop.GetValue(source), initialBag); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Array); + Test.AssertEquals(v.GetValueSubType(), Eina.ValueType.Int32); + + Test.AssertEquals(v[0], initialBag[0]); + Test.AssertEquals(v[1], initialBag[1]); + Test.AssertEquals(v[2], initialBag[2]); + + v[0] = 100; + v[1] = 200; + v[2] = 300; + + prop.SetValue(source, v.Unwrap()); + + IEnumerable newVal = prop.GetValue(source) as IEnumerable; + var toCheck = newVal.ToList(); + + Test.AssertEquals(toCheck[0], 100); + Test.AssertEquals(toCheck[1], 200); + Test.AssertEquals(toCheck[2], 300); + } + + public static void TestObjectContainerFromToObject() + { + var initialBag = new Eina.Array(); + initialBag.Push(new Dummy.TestObject()); + initialBag.Push(new Dummy.TestObject()); + initialBag.Push(new Dummy.TestObject()); + + var source = new ComplexHolder { BagOfObjects = initialBag }; + var prop = source.GetType().GetProperty("BagOfObjects"); + var v = new Eina.Value(prop.GetValue(source)); + Test.AssertEquals(prop.GetValue(source), initialBag); + + Test.AssertEquals(v.GetValueType(), Eina.ValueType.Array); + Test.AssertEquals(v.GetValueSubType(), Eina.ValueType.Object); + + Test.AssertEquals(v[0], initialBag[0]); + Test.AssertEquals(v[1], initialBag[1]); + Test.AssertEquals(v[2], initialBag[2]); + + var first = new Dummy.TestObject(); + var second = new Dummy.TestObject(); + var third = new Dummy.TestObject(); + v[0] = first; + v[1] = second; + v[2] = third; + + prop.SetValue(source, v.Unwrap()); + + IEnumerable newVal = prop.GetValue(source) as IEnumerable; + var toCheck = newVal.ToList(); + + Test.AssertEquals(toCheck[0], first); + Test.AssertEquals(toCheck[1], second); + Test.AssertEquals(toCheck[2], third); + } +} #pragma warning restore 1591 } diff --git a/src/tests/eina_cxx/eina_cxx_test_optional.cc b/src/tests/eina_cxx/eina_cxx_test_optional.cc index 381198c288..5eb2631451 100644 --- a/src/tests/eina_cxx/eina_cxx_test_optional.cc +++ b/src/tests/eina_cxx/eina_cxx_test_optional.cc @@ -102,7 +102,14 @@ EFL_START_TEST(eina_cxx_optional_assignment) assert(!a); assert(b); assert(c); assert(d); + // NOTE: resistance to self assignment is exactly what is being tested here, + // so this compilation warning can be suppressed. +#pragma GCC diagnostic push +#ifdef __clang__ +#pragma GCC diagnostic ignored "-Wself-assign-overloaded" +#endif a = a; +#pragma GCC diagnostic pop ck_assert(a == a); ck_assert(!a); diff --git a/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc index be6b16395d..12c375a112 100644 --- a/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc +++ b/src/tests/eina_cxx/eina_cxx_test_ptrlist.cc @@ -385,7 +385,7 @@ EFL_START_TEST(eina_cxx_ptrlist_constructors) efl::eina::list list2(10, w1); ck_assert(list2.size() == 10); ck_assert(std::find_if(list2.begin(), list2.end() - , [&list2, w2] (wrapper i) + , [w2] (wrapper i) { return i == w2; } diff --git a/src/tests/elementary/efl_ui_test_spin_button.c b/src/tests/elementary/efl_ui_test_spin_button.c index c495c881a8..78b21a4046 100644 --- a/src/tests/elementary/efl_ui_test_spin_button.c +++ b/src/tests/elementary/efl_ui_test_spin_button.c @@ -40,17 +40,10 @@ _set_flag_quit(void *data, const Efl_Event *ev) } static void -click_object(Efl_Part *obj) +click_spin_part(Eo *obj, const char *part) { get_me_to_those_events(spin); - - Evas *e = evas_object_evas_get(spin); - //this deletes the part - Eina_Rect r = efl_gfx_entity_geometry_get(obj); - evas_event_feed_mouse_move(e, r.x+r.w/2, r.y+r.h/2, 1234, NULL); - evas_event_feed_mouse_down(e, 1, 0, 1235, NULL); - evas_event_feed_mouse_up(e, 1, 0, 1236, NULL); - edje_object_message_signal_process(obj); + click_part(obj, part); } EFL_START_TEST (spin_value_events) @@ -134,7 +127,7 @@ EFL_START_TEST (spin_value_inc) efl_event_callback_add(spin, EFL_UI_SPIN_EVENT_MAX_REACHED, _set_flag, &max_reached); efl_event_callback_add(spin, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, _set_flag_quit, &delay_changed); - click_object(efl_content_get(efl_part(spin, "efl.inc_button"))); + click_spin_part(spin, "efl.inc_button"); ck_assert_int_eq(changed, EINA_TRUE); ck_assert_int_eq(min_reached, EINA_FALSE); @@ -159,7 +152,7 @@ EFL_START_TEST (spin_value_inc_max) efl_event_callback_add(spin, EFL_UI_SPIN_EVENT_MAX_REACHED, _set_flag, &max_reached); efl_event_callback_add(spin, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, _set_flag_quit, &delay_changed); - click_object(efl_content_get(efl_part(spin, "efl.inc_button"))); + click_spin_part(spin, "efl.inc_button"); ck_assert_int_eq(changed, EINA_TRUE); ck_assert_int_eq(min_reached, EINA_FALSE); @@ -184,7 +177,7 @@ EFL_START_TEST (spin_value_dec_min) efl_event_callback_add(spin, EFL_UI_SPIN_EVENT_MAX_REACHED, _set_flag, &max_reached); efl_event_callback_add(spin, EFL_UI_SPIN_BUTTON_EVENT_DELAY_CHANGED, _set_flag_quit, &delay_changed); - click_object(efl_content_get(efl_part(spin, "efl.dec_button"))); + click_spin_part(spin, "efl.dec_button"); ck_assert_int_eq(changed, EINA_TRUE); ck_assert_int_eq(min_reached, EINA_TRUE); diff --git a/src/tests/elementary/elm_test_progressbar.c b/src/tests/elementary/elm_test_progressbar.c index 17abdb36af..4435fa6ed6 100644 --- a/src/tests/elementary/elm_test_progressbar.c +++ b/src/tests/elementary/elm_test_progressbar.c @@ -59,9 +59,20 @@ EFL_START_TEST(elm_atspi_role_get) } EFL_END_TEST +EFL_START_TEST(elm_progressbar_unit_format_get_n) +{ + const char *fmt; + + fmt = elm_progressbar_unit_format_get(NULL); + + ck_assert(fmt == NULL); +} +EFL_END_TEST + void elm_test_progressbar(TCase *tc) { tcase_add_test(tc, elm_progressbar_legacy_type_check); tcase_add_test(tc, elm_progressbar_custom_unit_check); tcase_add_test(tc, elm_atspi_role_get); + tcase_add_test(tc, elm_progressbar_unit_format_get_n); } diff --git a/src/tests/elementary/elm_test_slider.c b/src/tests/elementary/elm_test_slider.c index 14035b4e48..76201fa305 100644 --- a/src/tests/elementary/elm_test_slider.c +++ b/src/tests/elementary/elm_test_slider.c @@ -135,10 +135,48 @@ EFL_START_TEST(elm_slider_events) } EFL_END_TEST +EFL_START_TEST(elm_slider_indicator_format_set_get_p) +{ + Evas_Object *win, *slider; + const char *fmt; + + win = win_add(NULL, "slider", ELM_WIN_BASIC); + slider = elm_slider_add(win); + elm_slider_indicator_format_set(slider, "%1.0f"); + fmt = elm_slider_indicator_format_get(slider); + + ck_assert(fmt != NULL); + ck_assert(!strcmp(fmt, "%1.0f")); +} +EFL_END_TEST + +EFL_START_TEST(elm_slider_indicator_format_get_n) +{ + const char *fmt; + + fmt = elm_slider_indicator_format_get(NULL); + + ck_assert(fmt == NULL); +} +EFL_END_TEST + +EFL_START_TEST(elm_slider_unit_format_get_n) +{ + const char *fmt; + + fmt = elm_slider_unit_format_get(NULL); + + ck_assert(fmt == NULL); +} +EFL_END_TEST + void elm_test_slider(TCase *tc) { tcase_add_test(tc, elm_slider_legacy_type_check); tcase_add_test(tc, elm_slider_in_scroller); tcase_add_test(tc, elm_slider_events); tcase_add_test(tc, elm_atspi_role_get); + tcase_add_test(tc, elm_slider_indicator_format_set_get_p); + tcase_add_test(tc, elm_slider_indicator_format_get_n); + tcase_add_test(tc, elm_slider_unit_format_get_n); } diff --git a/src/tests/elementary/spec/generator.py b/src/tests/elementary/spec/generator.py index f8ba0a2dcc..daf2e61cfc 100755 --- a/src/tests/elementary/spec/generator.py +++ b/src/tests/elementary/spec/generator.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 fixture_gen_template = """ static void diff --git a/src/tests/elementary/suite_helpers.c b/src/tests/elementary/suite_helpers.c index 9d73c5d26b..ee2efcb8d4 100644 --- a/src/tests/elementary/suite_helpers.c +++ b/src/tests/elementary/suite_helpers.c @@ -390,3 +390,25 @@ get_me_to_those_events(Eo *obj) evas_event_callback_add(e, EVAS_CALLBACK_RENDER_POST, events_norendered, NULL); ecore_main_loop_begin(); } + +void +click_object(Eo *obj) +{ + Evas *e = evas_object_evas_get(obj); + Eina_Rect r = efl_gfx_entity_geometry_get(obj); + evas_event_feed_mouse_move(e, r.x + r.w / 2, r.y + r.h / 2, 0, NULL); + evas_event_feed_mouse_down(e, 1, 0, 0, NULL); + evas_event_feed_mouse_up(e, 1, 0, 0, NULL); +} + +void +click_part(Eo *obj, const char *part) +{ + Efl_Part *part_obj = efl_ref(efl_part(obj, part)); + Eo *content = efl_content_get(part_obj); + click_object(content); + if (efl_isa(content, EFL_LAYOUT_SIGNAL_INTERFACE)) + edje_object_message_signal_process(content); + edje_object_message_signal_process(obj); + efl_unref(part_obj); +} diff --git a/src/tests/elementary/suite_helpers.h b/src/tests/elementary/suite_helpers.h index 12536d3884..9c1bd2a866 100644 --- a/src/tests/elementary/suite_helpers.h +++ b/src/tests/elementary/suite_helpers.h @@ -11,4 +11,6 @@ void fail_on_errors_teardown(void); void fail_on_errors_setup(void); void get_me_to_those_events(Eo *obj); +void click_object(Eo *obj); +void click_part(Eo *obj, const char *part); #endif diff --git a/src/tests/evas/evas_test_image.c b/src/tests/evas/evas_test_image.c index 19ae8ffb6a..1eaa6d0e2e 100644 --- a/src/tests/evas/evas_test_image.c +++ b/src/tests/evas/evas_test_image.c @@ -655,6 +655,9 @@ _file_to_memory(const char *filename, char **result) return size; } +static const Efl_Gfx_Image_Stretch_Region hsz[] = { { 8, 8 }, { 16, 555 } }; +static const Efl_Gfx_Image_Stretch_Region vsz[] = { { 8, 8 }, { 16, 512 } }; + EFL_START_TEST(evas_object_image_cached_data_comparision) { int i; @@ -666,6 +669,7 @@ EFL_START_TEST(evas_object_image_cached_data_comparision) const uint32_t *d2, *n_d2; const char *img_path, *img_path2; Evas_Object *img, *img2; + Eina_Rect region; Evas *e = _setup_evas(); @@ -727,6 +731,26 @@ EFL_START_TEST(evas_object_image_cached_data_comparision) fail_if(w2 != n_w2 || h2 != n_h2); fail_if(memcmp(d2, n_d2, w2 * h2 * 4)); } + + region = efl_gfx_image_content_region_get(img); + ck_assert_int_eq(region.x, 0); + ck_assert_int_eq(region.y, 0); + ck_assert_int_eq(region.w, 250); + ck_assert_int_eq(region.h, 250); + efl_gfx_image_border_set(img, 7, 14, 5, 10); + region = efl_gfx_image_content_region_get(img); + ck_assert_int_eq(region.x, 7); + ck_assert_int_eq(region.y, 5); + ck_assert_int_eq(region.w, 250 - 7 - 14); + ck_assert_int_eq(region.h, 250 - 5 - 10); + + efl_gfx_image_stretch_region_set(img, EINA_C_ARRAY_ITERATOR_NEW(hsz), + EINA_C_ARRAY_ITERATOR_NEW(vsz)); + region = efl_gfx_image_content_region_get(img); + ck_assert_int_eq(region.x, 8); + ck_assert_int_eq(region.y, 8); + ck_assert_int_eq(region.w, 120); + ck_assert_int_eq(region.h, 77); } EFL_END_TEST @@ -1005,6 +1029,94 @@ EFL_START_TEST(evas_object_image_jp2k_loader_data) EFL_END_TEST #endif +EFL_START_TEST(evas_object_image_9patch) +{ + Evas *e = _setup_evas(); + Evas *sub_e; + Ecore_Evas *ee, *sub_ee; + Evas_Object *obj, *cmp, *ref; + Eina_Strbuf *str; + + const char *files[] = { + "9patch_test.9.png" + }; + unsigned int i; + + ee = ecore_evas_ecore_evas_get(e); + + cmp = ecore_evas_object_image_new(ee); + evas_object_image_filled_set(cmp, EINA_TRUE); + evas_object_image_size_set(cmp, 1024, 1024); + evas_object_resize(cmp, 1024, 1024); + evas_object_show(cmp); + + sub_ee = ecore_evas_object_ecore_evas_get(cmp); + sub_e = ecore_evas_object_evas_get(cmp); + + ecore_evas_alpha_set(sub_ee, EINA_TRUE); + + obj = evas_object_rectangle_add(sub_e); + evas_object_color_set(obj, 0, 0, 0, 0); + evas_object_move(obj, 0, 0); + evas_object_resize(obj, 1024, 1024); + evas_object_show(obj); + + obj = evas_object_image_filled_add(sub_e); + evas_object_image_alpha_set(obj, 1); + evas_object_move(obj, 0, 0); + evas_object_resize(obj, 1024, 1024); + ecore_evas_resize(sub_ee, 1024, 1024); + evas_object_show(obj); + + Evas_Object *rect = evas_object_rectangle_add(sub_e); + evas_object_color_set(rect, 128, 0, 0, 128); + evas_object_show(rect); + + ref = evas_object_image_add(e); + str = eina_strbuf_new(); + + for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) + { + Eina_Rect content; + int r_w, r_h; + const uint32_t *d, *r_d; + + eina_strbuf_append_printf(str, "%s/%s", TESTS_IMG_DIR, files[i]); + evas_object_image_file_set(obj, eina_strbuf_string_get(str), NULL); + ck_assert_int_eq(evas_object_image_load_error_get(obj), EVAS_LOAD_ERROR_NONE); + content = efl_gfx_image_content_region_get(obj); + + evas_object_move(rect, content.x, content.y); + evas_object_resize(rect, content.w, content.h); + + eina_strbuf_reset(str); + + ecore_evas_manual_render(ee); + + d = evas_object_image_data_get(cmp, EINA_FALSE); + + eina_strbuf_append_printf(str, "%s/%s.png", TESTS_IMG_DIR, files[i]); + evas_object_image_file_set(ref, eina_strbuf_string_get(str), NULL); + ck_assert_int_eq(evas_object_image_load_error_get(ref), EVAS_LOAD_ERROR_NONE); + evas_object_image_size_get(ref, &r_w, &r_h); + r_d = evas_object_image_data_get(ref, EINA_FALSE); + + eina_strbuf_reset(str); + + fail_if(r_w != 1024 || r_h != 1024); + for (int i = 0; i < r_w * r_h; i++) + fail_if(((d[i] - r_d[i]) & 0xF8F8F8F8) != 0); + } + + evas_object_del(obj); + evas_object_del(ref); + + eina_strbuf_free(str); + + evas_free(e); +} +EFL_END_TEST + void evas_test_image_object(TCase *tc) { tcase_add_test(tc, evas_object_image_api); @@ -1030,6 +1142,7 @@ void evas_test_image_object(TCase *tc) #endif tcase_add_test(tc, evas_object_image_partially_load_orientation); tcase_add_test(tc, evas_object_image_cached_data_comparision); + tcase_add_test(tc, evas_object_image_9patch); } diff --git a/src/tests/evas/evas_tests_helpers.h b/src/tests/evas/evas_tests_helpers.h index af970b1a11..b3a3063790 100644 --- a/src/tests/evas/evas_tests_helpers.h +++ b/src/tests/evas/evas_tests_helpers.h @@ -21,19 +21,10 @@ while (0) static Evas * _setup_evas() { - Evas *evas; - Evas_Engine_Info *einfo; + Ecore_Evas *ee; - evas = evas_new(); - - evas_output_method_set(evas, evas_render_method_lookup("buffer")); - einfo = evas_engine_info_get(evas); - evas_engine_info_set(evas, einfo); - - evas_output_size_set(evas, 500, 500); - evas_output_viewport_set(evas, 0, 0, 500, 500); - - return evas; + ee = ecore_evas_buffer_new(500, 500); + return ecore_evas_get(ee); } #endif diff --git a/src/tests/evas/images/9patch_test.9.png b/src/tests/evas/images/9patch_test.9.png new file mode 100644 index 0000000000..7e579d2498 Binary files /dev/null and b/src/tests/evas/images/9patch_test.9.png differ diff --git a/src/tests/evas/images/9patch_test.9.png.png b/src/tests/evas/images/9patch_test.9.png.png new file mode 100644 index 0000000000..e1d0549634 Binary files /dev/null and b/src/tests/evas/images/9patch_test.9.png.png differ