/* * Copyright (C) Ascensio System SIA, 2009-2026 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation, together with the * additional terms provided in the LICENSE file. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: https://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA by email at info@onlyoffice.com * or by postal mail at 20A-6 Ernesta Birznieka-Upisha Street, Riga, * LV-1050, Latvia, European Union. * * The interactive user interfaces in modified versions of the Program * are required to display Appropriate Legal Notices in accordance with * Section 5 of the GNU AGPL version 3. * * No trademark rights are granted under this License. * * All non-code elements of the Product, including illustrations, * icon sets, and technical writing content, are licensed under the * Creative Commons Attribution-ShareAlike 4.0 International License: * https://creativecommons.org/licenses/by-sa/4.0/legalcode * * This license applies only to such non-code elements and does not * modify or replace the licensing terms applicable to the Program's * source code, which remains licensed under the GNU Affero General * Public License v3. * * SPDX-License-Identifier: AGPL-3.0-only */ #include "table.h" #include #include "serialize_elements.h" #include "odfcontext.h" #include "odf_document.h" #include "odf_document_impl.h" #include "office_document.h" #include "style_table_properties.h" #include "style_graphic_properties.h" #include "draw_common.h" namespace cpdoccore { using namespace odf_types; namespace odf_reader { bool table_table_cell_content::pptx_convert(oox::pptx_conversion_context & Context) { bool wasPar = false; for (size_t i = 0; i < elements_.size(); i++) { if (elements_[i]->get_type() == typeTextP || elements_[i]->get_type() == typeTextH) wasPar = true; elements_[i]->pptx_convert(Context); } return wasPar; } void table_table_row::pptx_convert(oox::pptx_conversion_context & Context) { std::wostream & _Wostream = Context.get_table_context().tableData(); const std::wstring styleName = attlist_.table_style_name_.get_value_or(L""); const std::wstring defaultCellStyle = attlist_.table_default_cell_style_name_.get_value_or(L""); std::wstring template_style_name = L""; if (Context.get_table_context().template_is_first_row()) template_style_name = Context.get_table_context().get_first_row_style_name(); else if (Context.get_table_context().template_is_last_row()) template_style_name = Context.get_table_context().get_last_row_style_name(); else if (Context.get_table_context().template_is_odd_row()) template_style_name = Context.get_table_context().get_odd_rows_style_name(); Context.get_table_context().set_template_row_style_name(template_style_name); for (unsigned int i = 0; i < attlist_.table_number_rows_repeated_; ++i) { int height = 0; const style_instance * inst = Context.root()->odf_context().styleContainer().style_by_name( styleName , style_family::TableRow,true); if ((inst) && (inst->content()) && (inst->content()->get_style_table_row_properties())) { style_table_row_properties_attlist & row_attlist = inst->content()->get_style_table_row_properties()->attlist_; if (row_attlist.style_row_height_) { height = (int)( 0.5 + row_attlist.style_row_height_->get_value_unit(length::emu) ); } else if (row_attlist.style_min_row_height_) { height = (int)( 0.5 + row_attlist.style_min_row_height_->get_value_unit(length::emu)); } } if (height < 1) height = 100000; _Wostream << L""; Context.get_table_context().start_row(styleName, defaultCellStyle); Context.get_table_context().set_table_columns(content_.size()); for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } Context.get_table_context().end_row(); _Wostream << L""; } } void table_table_rows::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_table_header_rows::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_rows::pptx_convert(oox::pptx_conversion_context & Context) { if (table_table_rows_) table_table_rows_->pptx_convert(Context); else { Context.get_table_context().set_table_rows(table_table_row_.size()); for (size_t i = 0; i < table_table_row_.size(); i++) { table_table_row_[i]->pptx_convert(Context); } } } void table_rows_no_group::pptx_convert(oox::pptx_conversion_context & Context) { table_rows_1_.pptx_convert(Context); if (table_table_header_rows_) table_table_header_rows_->pptx_convert(Context); table_rows_2_.pptx_convert(Context); } void table_rows_and_groups::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_table::pptx_convert(oox::pptx_conversion_context & Context) { Context.get_slide_context().start_table(); ////////////////////////////////////////////////////////////////// std::wstring tableStyleName = attlist_.table_style_name_.get_value_or(L""); Context.get_table_context().start_table(tableStyleName); if (attlist_.table_template_name_) { std::wstring name = L"table:" + attlist_.table_template_name_.get() ; if (office_element_ptr style = Context.root()->odf_context().Templates().find_by_style_name(name)) { if (table_table_template* template_ = dynamic_cast(style.get())) { //first row, columns, last row, columns, odd row, columns todoooo if (template_->table_body_) { table_body_template* body_ = dynamic_cast(template_->table_body_.get()); Context.get_table_context().set_default_cell_style(body_->table_style_name_); } if (template_->table_first_row_) { table_first_row_template* first_row_ = dynamic_cast(template_->table_first_row_.get()); Context.get_table_context().set_first_row_style_name(first_row_->table_style_name_); } if (template_->table_last_row_) { table_last_row_template* last_row_ = dynamic_cast(template_->table_last_row_.get()); Context.get_table_context().set_last_row_style_name(last_row_->table_style_name_); } if (template_->table_odd_rows_) { table_odd_rows_template* odd_rows_ = dynamic_cast(template_->table_odd_rows_.get()); Context.get_table_context().set_odd_rows_style_name(odd_rows_->table_style_name_); } if (template_->table_first_column_) { table_first_column_template* first_column_ = dynamic_cast(template_->table_first_column_.get()); Context.get_table_context().set_first_column_style_name(first_column_->table_style_name_); } if (template_->table_last_column_) { table_last_column_template* last_column = dynamic_cast(template_->table_last_column_.get()); Context.get_table_context().set_last_column_style_name(last_column->table_style_name_); } if (template_->table_odd_columns_) { table_odd_columns_template* odd_columns = dynamic_cast(template_->table_odd_columns_.get()); Context.get_table_context().set_odd_columns_style_name(odd_columns->table_style_name_); } Context.get_table_context().set_template_use_styles( attlist_.table_use_first_row_styles_, attlist_.table_use_last_row_styles_, attlist_.table_use_banding_rows_styles_, attlist_.table_use_first_column_styles_, attlist_.table_use_last_column_styles_, attlist_.table_use_banding_columns_styles_); } } } std::wostream & _Wostream = Context.get_table_context().tableData(); _Wostream << L""; _Wostream << L""; style_instance * inst = Context.root()->odf_context().styleContainer().style_by_name( tableStyleName, style_family::Table, true); if ((inst) && (inst->content())) { if (inst->content()->get_graphic_properties()) { oox::_oox_fill fill; graphic_format_properties * graphic_props = inst->content()->get_graphic_properties(); if (graphic_props) Compute_GraphicFill(graphic_props->common_draw_fill_attlist_, graphic_props->style_background_image_, Context.root(), fill); if (fill.bitmap) { bool isMediaInternal = false; std::wstring ref; fill.bitmap->rId = Context.get_slide_context().get_mediaitems()->add_or_find(fill.bitmap->xlink_href_, oox::typeImage, isMediaInternal, ref, oox::document_place); Context.get_slide_context().add_rels(isMediaInternal, fill.bitmap->rId, ref, oox::typeImage); } oox::oox_serialize_fill(_Wostream, fill); } } _Wostream << L""; _Wostream << L""; table_columns_and_groups_.pptx_convert(Context); _Wostream << L""; table_rows_and_groups_.pptx_convert(Context); Context.get_table_context().end_table(); _Wostream << L""; //////////////////////////////////////////////////////////////////////// std::wstring table_content_ = Context.get_table_context().tableData().str(); if (!table_content_.empty()) { Context.get_slide_context().set_property(_property(L"table-content", table_content_)); } Context.get_slide_context().end_table(); } void table_columns::pptx_convert(oox::pptx_conversion_context & Context) { if (table_table_columns_) table_table_columns_->pptx_convert(Context); for (size_t i = 0; i < table_table_column_.size(); i++) { table_table_column_[i]->pptx_convert(Context); } } void table_table_columns::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_columns_no_group::pptx_convert(oox::pptx_conversion_context & Context) { table_columns_1_.pptx_convert(Context); if (table_table_header_columns_) table_table_header_columns_->pptx_convert(Context); table_columns_2_.pptx_convert(Context); } void table_columns_and_groups::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_table_header_columns::pptx_convert(oox::pptx_conversion_context & Context) { for (size_t i = 0; i < content_.size(); i++) { content_[i]->pptx_convert(Context); } } void table_table_column_group::pptx_convert(oox::pptx_conversion_context & Context) { table_columns_and_groups_.pptx_convert(Context); } void table_table_column::pptx_convert(oox::pptx_conversion_context & Context) { std::wostream & _Wostream = Context.get_table_context().tableData(); const unsigned int columnsRepeated = attlist_.table_number_columns_repeated_; const std::wstring defaultCellStyle = attlist_.table_default_cell_style_name_.get_value_or(L""); Context.get_table_context().start_column(columnsRepeated, defaultCellStyle); for (unsigned int i = 0; i < columnsRepeated; ++i) { if (attlist_.table_style_name_) { const std::wstring colStyleName = attlist_.table_style_name_.get(); style_instance * inst = Context.root()->odf_context().styleContainer().style_by_name(colStyleName, style_family::TableColumn, true); if ((inst) && (inst->content())) { //column properies if (inst->content()->get_style_table_column_properties()) inst->content()->get_style_table_column_properties()->pptx_convert(Context); } } } } const wchar_t * emptyParTable = L"";// void table_table_cell::pptx_convert(oox::pptx_conversion_context & Context) { std::wostream & _Wostream = Context.get_table_context().tableData(); CP_XML_WRITER(_Wostream) { for (unsigned int r = 0; r < attlist_.table_number_columns_repeated_; ++r) { Context.get_table_context().start_cell(); unsigned int current_col = Context.get_table_context().current_column(); if (Context.get_table_context().template_is_first_column()) Context.get_table_context().set_default_cell_style_col(current_col, Context.get_table_context().get_first_column_style_name()); else if(Context.get_table_context().template_is_last_column()) Context.get_table_context().set_default_cell_style_col(current_col, Context.get_table_context().get_last_column_style_name()); else if (Context.get_table_context().template_is_odd_column()) Context.get_table_context().set_default_cell_style_col(current_col, Context.get_table_context().get_odd_column_style_name()); CP_XML_NODE(L"a:tc") { std::vector style_instances; std::wstring style_name; style_instance *style_inst = Context.root()->odf_context().styleContainer().style_default_by_type(odf_types::style_family::TableCell); if (!style_inst) { default_style* def_style = new default_style(); office_document_base* document = dynamic_cast(Context.root()->get_impl()->get_content()); office_automatic_styles* styles = dynamic_cast(document->office_automatic_styles_.get()); styles->styles_.style_style_.push_back(office_element_ptr(def_style)); style_table_cell_properties* props = def_style->content_.get_style_table_cell_properties(true); def_style->content_.style_family_ = odf_types::style_family::TableCell; props->attlist_.common_padding_attlist_.fo_padding_ = length(3600 / 12700., length::pt); Context.root()->odf_context().styleContainer().add_style(L"", L"", &(def_style->content_), false, true, L"", L"", L"", L"", L"default"); style_inst = Context.root()->odf_context().styleContainer().style_default_by_type(odf_types::style_family::TableCell); } if (style_inst) { style_table_cell_properties* props = style_inst->content()->get_style_table_cell_properties(true); if (!props->attlist_.common_padding_attlist_.fo_padding_) props->attlist_.common_padding_attlist_.fo_padding_ = length(3600 / 12700., length::pt); style_instances.push_back(style_inst); } style_name = Context.get_table_context().get_default_cell_style(); if (!style_name.empty()) { style_inst = Context.root()->odf_context().styleContainer().style_by_name(style_name, style_family::TableCell, true); if (style_inst) style_instances.push_back(style_inst); } style_name = Context.get_table_context().get_default_cell_style_col(Context.get_table_context().current_column()); if (!style_name.empty()) { style_inst = Context.root()->odf_context().styleContainer().style_by_name(style_name, style_family::TableCell, true); if (style_inst)style_instances.push_back(style_inst); } style_name = Context.get_table_context().get_template_row_style_name(); if (!style_name.empty() && !Context.get_table_context().template_is_first_column() && !Context.get_table_context().template_is_last_column()) { style_inst = Context.root()->odf_context().styleContainer().style_by_name(style_name, style_family::TableCell, true); if (style_inst)style_instances.push_back(style_inst); } if (!attlist_.table_style_name_.has_value()) { style_name = Context.get_table_context().get_default_cell_style_row(); if (!style_name.empty()) { style_inst = Context.root()->odf_context().styleContainer().style_by_name(style_name, style_family::TableCell, true); if (style_inst) style_instances.push_back(style_inst); } } style_name = attlist_.table_style_name_.get_value_or(L""); if (!style_name.empty()) { style_inst = Context.root()->odf_context().styleContainer().style_by_name(style_name, style_family::TableCell, true); if (style_inst) style_instances.push_back(style_inst); } if (attlist_extra_.table_number_rows_spanned_ > 1) { CP_XML_ATTR(L"rowSpan" , attlist_extra_.table_number_rows_spanned_); CP_XML_ATTR(L"vMerge", 1); Context.get_table_context().set_rows_spanned(Context.get_table_context().current_column(), attlist_extra_.table_number_rows_spanned_ - 1, attlist_extra_.table_number_columns_spanned_ - 1, style_name); } if (attlist_extra_.table_number_columns_spanned_ > 1) { //CP_XML_ATTR(L"hMerge", true); CP_XML_ATTR(L"gridSpan" , attlist_extra_.table_number_columns_spanned_); Context.get_table_context().set_columns_spanned(attlist_extra_.table_number_columns_spanned_ - 1); } Context.get_text_context().start_object(); bool presentText = content_.pptx_convert(Context); std::wstring cellContent = Context.get_text_context().end_object(); if (false == cellContent.empty()) { CP_XML_NODE(L"a:txBody") { CP_XML_NODE(L"a:bodyPr") { //CP_XML_ATTR(L"lIns", 3600); //CP_XML_ATTR(L"rIns", 3600); //CP_XML_ATTR(L"tIns", 3600); //CP_XML_ATTR(L"bIns", 3600); //CP_XML_NODE(L"a:noAutofit"); } CP_XML_STREAM() << cellContent; } } else { CP_XML_STREAM() << emptyParTable; } oox_serialize_tcPr(CP_XML_STREAM(), style_instances, Context); } Context.get_table_context().end_cell(); } } } void table_covered_table_cell::pptx_convert(oox::pptx_conversion_context & Context) { std::wostream & _Wostream = Context.get_table_context().tableData(); for (unsigned int i = 0; i < attlist_.table_number_columns_repeated_; ++i) { if (Context.get_table_context().start_covered_cell(Context)) { if (!content_.pptx_convert(Context)) { _Wostream << emptyParTable; } } Context.get_table_context().end_covered_cell(); } } } }