Files
core/OdfFile/Reader/Format/table_pptx.cpp
Elena Subbotina b1dff84b1b fix bug #74757
2025-08-01 15:32:24 +03:00

532 lines
19 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* 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. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* 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: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "table.h"
#include <xml/simple_xml_writer.h>
#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"<a:tr h=\"" << height << 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"</a:tr>";
}
}
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<table_table_template *>(style.get()))
{
//first row, columns, last row, columns, odd row, columns todoooo
if (template_->table_body_)
{
table_body_template* body_ = dynamic_cast<table_body_template* >(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<table_first_row_template*>(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<table_last_row_template*>(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<table_odd_rows_template*>(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<table_first_column_template*>(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<table_last_column_template*>(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<table_odd_columns_template*>(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"<a:tbl>";
_Wostream << L"<a:tblPr";
if (attlist_.table_use_banding_rows_styles_)
_Wostream << L" bandRow=\"1\"";
if (attlist_.table_use_first_row_styles_)
_Wostream << L" firstRow=\"1\"";
if (attlist_.table_use_banding_columns_styles_)
_Wostream << L" bandCol=\"1\"";
if (attlist_.table_use_first_column_styles_)
_Wostream << L" firstCol=\"1\"";
_Wostream << ">";
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"</a:tblPr>";
_Wostream << L"<a:tblGrid>";
table_columns_and_groups_.pptx_convert(Context);
_Wostream << L"</a:tblGrid>";
table_rows_and_groups_.pptx_convert(Context);
Context.get_table_context().end_table();
_Wostream << L"</a:tbl>";
////////////////////////////////////////////////////////////////////////
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"<a:txBody><a:bodyPr/><a:p></a:p></a:txBody>";//<a:endParaRPr/>
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<const style_instance *> 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<office_document_base*>(Context.root()->get_impl()->get_content());
office_automatic_styles* styles = dynamic_cast<office_automatic_styles*>(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();
}
}
}
}