From 503b9140e34ffb3eb44f0fb70af6115e455fa945 Mon Sep 17 00:00:00 2001 From: Kamil Kerimov Date: Tue, 19 Dec 2023 17:33:11 +0500 Subject: [PATCH] Fix bug #65366 Convert preset subtype --- .../Converter/pptx_animation_context.cpp | 6 + .../Reader/Converter/pptx_animation_context.h | 2 + OdfFile/Reader/Format/anim_elements.cpp | 143 +++++++++++++++--- OdfFile/Writer/Converter/PptxConverter.cpp | 108 ++++++++++++- OdfFile/Writer/Format/odp_page_state.cpp | 12 ++ OdfFile/Writer/Format/odp_page_state.h | 1 + 6 files changed, 253 insertions(+), 19 deletions(-) diff --git a/OdfFile/Reader/Converter/pptx_animation_context.cpp b/OdfFile/Reader/Converter/pptx_animation_context.cpp index d32a3aa749..437fd7ae76 100644 --- a/OdfFile/Reader/Converter/pptx_animation_context.cpp +++ b/OdfFile/Reader/Converter/pptx_animation_context.cpp @@ -144,6 +144,11 @@ namespace oox { SET_PAR_ANIMATION_ATTRIBUTE(PresetID, value); } + void pptx_animation_context::set_par_animation_preset_subtype(int value) + { + SET_PAR_ANIMATION_ATTRIBUTE(PresetSubtype, value); + } + void pptx_animation_context::set_par_animation_fill(const std::wstring& value) { SET_PAR_ANIMATION_ATTRIBUTE(Fill, value); @@ -763,6 +768,7 @@ namespace oox { { CP_XML_ATTR_OPT(L"presetClass" , PresetClass); CP_XML_ATTR_OPT(L"presetID" , PresetID); + CP_XML_ATTR_OPT(L"presetSubtype", PresetSubtype); CP_XML_ATTR_OPT(L"fill" , Fill); CP_XML_ATTR_OPT(L"accel" , Accelerate); CP_XML_ATTR_OPT(L"decel" , Decelerate); diff --git a/OdfFile/Reader/Converter/pptx_animation_context.h b/OdfFile/Reader/Converter/pptx_animation_context.h index d2a6897f57..644c798b11 100644 --- a/OdfFile/Reader/Converter/pptx_animation_context.h +++ b/OdfFile/Reader/Converter/pptx_animation_context.h @@ -71,6 +71,7 @@ namespace oox { _CP_OPT(std::wstring) End; _CP_OPT(std::wstring) PresetClass; _CP_OPT(int) PresetID; + _CP_OPT(int) PresetSubtype; _CP_OPT(std::wstring) Fill; _CP_OPT(int) Accelerate; _CP_OPT(int) Decelerate; @@ -295,6 +296,7 @@ namespace oox { void set_par_animation_end(const std::wstring& value); void set_par_animation_preset_class(const std::wstring& value); void set_par_animation_preset_id(int value); + void set_par_animation_preset_subtype(int value); void set_par_animation_fill(const std::wstring& value); void set_par_animation_accelerate(int value); void set_par_animation_decelerate(int value); diff --git a/OdfFile/Reader/Format/anim_elements.cpp b/OdfFile/Reader/Format/anim_elements.cpp index 041b95cbe3..d860a5c90f 100644 --- a/OdfFile/Reader/Format/anim_elements.cpp +++ b/OdfFile/Reader/Format/anim_elements.cpp @@ -63,8 +63,13 @@ struct preset_id_maping int OOX_PresetID; }; -// TODO: replace with unordered_map?? -static const preset_id_maping g_preset_id_map[] = { +struct preset_subtype_maping +{ + int OOX_PresetID; + std::wstring ODF_PresetID; +}; + +static const preset_id_maping s_preset_id_map[] = { { preset_id::type::ooo_entrance_appear , 1 }, { preset_id::type::ooo_entrance_fly_in , 2 }, { preset_id::type::ooo_entrance_venetian_blinds , 3 }, @@ -271,6 +276,31 @@ static const preset_id_maping g_preset_id_map[] = { { preset_id::type::none , 0 }, }; +static const preset_subtype_maping s_preset_subtype_maping[] = +{ + { 1, L"from-top" }, + { 2, L"from-right" }, + { 3, L"from-top-right" }, + { 4, L"from-bottom" }, + { 5, L"horizontal" }, + { 6, L"from-bottom-right" }, + { 8, L"from-left" }, + { 9, L"from-top-left" }, + { 10, L"vertical" }, + { 12, L"from-bottom-left" }, + { 16, L"in" }, + { 21, L"vertical-in" }, + { 26, L"horizontal-in" }, + { 32, L"out" }, + { 36, L"out-from-screen-center" }, + { 37, L"vertical-out" }, + { 42, L"horizontal-out" }, + { 272, L"in-slightly" }, + { 288, L"out-slightly" }, + { 528, L"in-from-screen-center" }, + { 0, L""} +}; + static std::wstring pptx_convert_smil_attribute_name(const odf_types::smil_attribute_name& smil_attribute_name_) { using namespace odf_types; @@ -445,6 +475,76 @@ void anim_par::add_attributes( const xml::attributes_wc_ptr & Attributes ) par_attlist_.add_attributes(Attributes); } +static _CP_OPT(int) pptx_convert_preset_subtype(const std::wstring& preset_class_, const int preset_id_, const std::wstring& preset_subtype_) +{ + _CP_OPT(int) pptx_preset_subtype; + + if ((preset_class_ == L"entr") || (preset_class_ == L"exit")) + { + // skip "wheel" preset id + if (preset_id_ != 21) + { + switch (preset_id_) + { + case 5: + { + if (preset_subtype_ == L"downward") + pptx_preset_subtype = 5; + else if (preset_subtype_ == L"across") + pptx_preset_subtype = 10; + } + break; + case 17: + { + if (preset_subtype_ == L"across") + pptx_preset_subtype = 10; + } + break; + case 18: + { + if (preset_subtype_ == L"right-to-top") + pptx_preset_subtype = 3; + else if (preset_subtype_ == L"right-to-bottom") + pptx_preset_subtype = 6; + else if (preset_subtype_ == L"left-to-top") + pptx_preset_subtype = 9; + else if (preset_subtype_ == L"left-to-bottom") + pptx_preset_subtype = 12; + } + break; + } + } + + if (!pptx_preset_subtype) + { + const preset_subtype_maping* p = s_preset_subtype_maping; + while (p->OOX_PresetID != 0) + { + if (preset_subtype_ == p->ODF_PresetID) + { + pptx_preset_subtype = p->OOX_PresetID; + break; + } + p++; + } + } + } + + if (!pptx_preset_subtype) + { + try + { + pptx_preset_subtype = boost::lexical_cast(preset_subtype_); + } + catch (const boost::bad_lexical_cast& e) + { + pptx_preset_subtype = boost::none; + } + } + + return pptx_preset_subtype; +} + void anim_par::pptx_convert(oox::pptx_conversion_context & Context) { oox::pptx_animation_context & animationContext = Context.get_slide_context().get_animation_context(); @@ -459,7 +559,7 @@ void anim_par::pptx_convert(oox::pptx_conversion_context & Context) _CP_OPT(std::wstring) presentationPresetClass; _CP_OPT(int) presentationPresetId; - _CP_OPT(std::wstring) presentationPresetPresetSubType; + _CP_OPT(int) presentationPresetPresetSubType; bool isSlideAnimation = false; // NOTE: Анимация применяется к самому слайду, а не элементу на слайде @@ -540,7 +640,13 @@ void anim_par::pptx_convert(oox::pptx_conversion_context & Context) break; default: presentationPresetClass = L"custom"; - } + } + + if (par_attlist_.presentation_preset_sub_type_ && presentationPresetId) + presentationPresetPresetSubType = pptx_convert_preset_subtype( + *presentationPresetClass, + *presentationPresetId, + *par_attlist_.presentation_preset_sub_type_); } if (common_attlist_.smil_fill_) @@ -567,17 +673,18 @@ void anim_par::pptx_convert(oox::pptx_conversion_context & Context) { animationContext.start_par_animation(); - if (presentationNodeType) animationContext.set_par_animation_presentation_node_type(presentationNodeType.value()); - if (direction) animationContext.set_par_animation_direction(direction.value()); - if (restart) animationContext.set_par_animation_restart(restart.value()); - if (duration) animationContext.set_par_animation_duration(duration.value()); - if (delay) animationContext.set_par_animation_delay(delay.value()); - if (end) animationContext.set_par_animation_end(end.value()); - if (presentationPresetClass) animationContext.set_par_animation_preset_class(presentationPresetClass.value()); - if (presentationPresetId) animationContext.set_par_animation_preset_id(presentationPresetId.value()); - if (fill) animationContext.set_par_animation_fill(fill.value()); - if (accelerate) animationContext.set_par_animation_accelerate(accelerate.value()); - if (decelerate) animationContext.set_par_animation_decelerate(decelerate.value()); + if (presentationNodeType) animationContext.set_par_animation_presentation_node_type(presentationNodeType.value()); + if (direction) animationContext.set_par_animation_direction(direction.value()); + if (restart) animationContext.set_par_animation_restart(restart.value()); + if (duration) animationContext.set_par_animation_duration(duration.value()); + if (delay) animationContext.set_par_animation_delay(delay.value()); + if (end) animationContext.set_par_animation_end(end.value()); + if (presentationPresetClass) animationContext.set_par_animation_preset_class(presentationPresetClass.value()); + if (presentationPresetId) animationContext.set_par_animation_preset_id(presentationPresetId.value()); + if (presentationPresetPresetSubType) animationContext.set_par_animation_preset_subtype(presentationPresetPresetSubType.value()); + if (fill) animationContext.set_par_animation_fill(fill.value()); + if (accelerate) animationContext.set_par_animation_accelerate(accelerate.value()); + if (decelerate) animationContext.set_par_animation_decelerate(decelerate.value()); } animationContext.set_is_slide_animation(isSlideAnimation); @@ -617,10 +724,10 @@ boost::optional anim_par::pptx_convert_preset_id() { preset_id::type presetID = par_attlist_.presentation_preset_id_.value().get_type(); - for (size_t i = 0; g_preset_id_map[i].ODF_PresetID != preset_id::type::none; i++) + for (size_t i = 0; s_preset_id_map[i].ODF_PresetID != preset_id::type::none; i++) { - if (g_preset_id_map[i].ODF_PresetID == presetID) - return g_preset_id_map[i].OOX_PresetID; + if (s_preset_id_map[i].ODF_PresetID == presetID) + return s_preset_id_map[i].OOX_PresetID; } return 0; diff --git a/OdfFile/Writer/Converter/PptxConverter.cpp b/OdfFile/Writer/Converter/PptxConverter.cpp index 2db929d366..81143120cd 100644 --- a/OdfFile/Writer/Converter/PptxConverter.cpp +++ b/OdfFile/Writer/Converter/PptxConverter.cpp @@ -1847,6 +1847,99 @@ void PptxConverter::convert(PPTX::Logic::ZoomTransition *oox_transition) odp_context->current_slide().set_transition_type(11); } +struct preset_subtype_maping +{ + int OOX_PresetSubtype; + std::wstring ODF_PresetSubtype; +}; + +static const preset_subtype_maping s_preset_subtype_maping[] = +{ + { 1, L"from-top" }, + { 2, L"from-right" }, + { 3, L"from-top-right" }, + { 4, L"from-bottom" }, + { 5, L"horizontal" }, + { 6, L"from-bottom-right" }, + { 8, L"from-left" }, + { 9, L"from-top-left" }, + { 10, L"vertical" }, + { 12, L"from-bottom-left" }, + { 16, L"in" }, + { 21, L"vertical-in" }, + { 26, L"horizontal-in" }, + { 32, L"out" }, + { 36, L"out-from-screen-center" }, + { 37, L"vertical-out" }, + { 42, L"horizontal-out" }, + { 272, L"in-slightly" }, + { 288, L"out-slightly" }, + { 528, L"in-from-screen-center" }, + { 0, L"" } +}; + +static std::wstring convert_subtype(PPTX::Limit::TLPresetClass preset_class_, int preset_id_, int preset_subtype_) +{ + std::wstring subtype; + + const unsigned char entrance_bytecode = 1; + const unsigned char exit_bytecode = 2; + + if ((preset_class_.GetBYTECode() == entrance_bytecode) || (preset_class_.GetBYTECode() == exit_bytecode)) + { + // skip wheel effect + if (preset_id_ != 21) + { + if (preset_id_ == 5) + { + // checkerboard + switch (preset_subtype_) + { + case 5: subtype = L"downward"; break; + case 10: subtype = L"across"; break; + } + } + else if (preset_id_ == 17) + { + // stretch + if (preset_subtype_ == 10) + subtype = L"across"; + } + else if (preset_id_ == 18) + { + // strips + switch (preset_subtype_) + { + case 3: subtype = L"right-to-top"; break; + case 6: subtype = L"right-to-bottom"; break; + case 9: subtype = L"left-to-top"; break; + case 12: subtype = L"left-to-bottom"; break; + } + } + + if (subtype.empty()) + { + const preset_subtype_maping* p = s_preset_subtype_maping; + + while (p->OOX_PresetSubtype != 0) + { + if (p->OOX_PresetSubtype == preset_subtype_) + { + subtype = p->ODF_PresetSubtype; + break; + } + p++; + } + } + } + } + + if (subtype.empty() && preset_subtype_ != 0) + return std::to_wstring(preset_subtype_); + + return subtype; +} + void PptxConverter::convert(PPTX::Logic::CTn *oox_time_common) { if (!oox_time_common) return; @@ -1881,10 +1974,23 @@ void PptxConverter::convert(PPTX::Logic::CTn *oox_time_common) if (oox_time_common->presetClass.IsInit()) { convert(*oox_time_common->presetClass); - if(oox_time_common->presetID.IsInit()) + if (oox_time_common->presetID.IsInit()) + { convert(*oox_time_common->presetClass, *oox_time_common->presetID); + + if (oox_time_common->presetSubtype.IsInit()) + { + const std::wstring odf_subtype = convert_subtype( + *oox_time_common->presetClass, + *oox_time_common->presetID, + *oox_time_common->presetSubtype); + if(!odf_subtype.empty()) + odp_context->current_slide().set_anim_subtype(odf_subtype); + } + } } + //nullable stCondLst; //nullable endCondLst; diff --git a/OdfFile/Writer/Format/odp_page_state.cpp b/OdfFile/Writer/Format/odp_page_state.cpp index c85a38db56..bc61f61a19 100644 --- a/OdfFile/Writer/Format/odp_page_state.cpp +++ b/OdfFile/Writer/Format/odp_page_state.cpp @@ -290,6 +290,18 @@ void odp_page_state::set_anim_auto_reverse(bool val) anim_levels.back().attlist->smil_auto_reverse_ = val; } +void odp_page_state::set_anim_subtype(const std::wstring& val) +{ + if (anim_levels.empty()) return; + if (!anim_levels.back().attlist)return; + + anim_par* animate = dynamic_cast(anim_levels.back().elm.get()); + if (!animate) + return; + + anim_levels.back().par_attlist->presentation_preset_sub_type_ = val; +} + void odp_page_state::set_anim_animation_formula(const std::wstring& val) { if (anim_levels.empty()) return; diff --git a/OdfFile/Writer/Format/odp_page_state.h b/OdfFile/Writer/Format/odp_page_state.h index 120a13d622..e14d66beba 100644 --- a/OdfFile/Writer/Format/odp_page_state.h +++ b/OdfFile/Writer/Format/odp_page_state.h @@ -146,6 +146,7 @@ public: void set_anim_to (const std::wstring& val); void set_anim_target_element(const std::wstring& val); void set_anim_auto_reverse (bool val); + void set_anim_subtype (const std::wstring& val); void set_anim_animation_formula(const std::wstring& val); void set_anim_animation_keytimes(const odf_types::smil_key_times& val);