mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 05:24:10 +08:00
Co-authored-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com> Co-committed-by: Alexander Trofimov <alexander.trofimov@onlyoffice.com>
358 lines
9.6 KiB
C++
358 lines
9.6 KiB
C++
/*
|
|
* 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 "oox_plot_area.h"
|
|
|
|
#include <random>
|
|
|
|
#include <xml/simple_xml_writer.h>
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include "../Format/odfcontext.h"
|
|
#include "../Format/style_text_properties.h"
|
|
#include "../Format/style_chart_properties.h"
|
|
|
|
#include "oox_chart_shape.h"
|
|
|
|
#include "../../DataTypes/chartclass.h"
|
|
|
|
namespace cpdoccore {
|
|
namespace oox {
|
|
oox_plot_area::oox_plot_area() : no_used_local_tables_(false)
|
|
{
|
|
std::random_device rd;
|
|
std::mt19937 gen(rd());
|
|
std::uniform_int_distribution<> distrib(1001, 9999);
|
|
|
|
axis_id_ += distrib(gen);
|
|
}
|
|
|
|
void oox_plot_area::add_chart(int type)
|
|
{
|
|
oox_chart_ptr chart;
|
|
switch (type)
|
|
{
|
|
case odf_types::chart_class::line:
|
|
chart = oox_line_chart::create();
|
|
break;
|
|
case odf_types::chart_class::area:
|
|
chart = oox_area_chart::create();
|
|
break;
|
|
case odf_types::chart_class::circle:
|
|
chart = oox_pie_chart::create();
|
|
break;
|
|
case odf_types::chart_class::ring:
|
|
chart = oox_doughnut_chart::create();
|
|
break;
|
|
case odf_types::chart_class::scatter:
|
|
chart = oox_scatter_chart::create();
|
|
break;
|
|
case odf_types::chart_class::radar:
|
|
chart = oox_radar_chart::create();
|
|
break;
|
|
case odf_types::chart_class::bar:
|
|
chart = oox_bar_chart::create();
|
|
break;
|
|
case odf_types::chart_class::stock:
|
|
chart = oox_stock_chart::create();
|
|
break;
|
|
case odf_types::chart_class::bubble:
|
|
chart = oox_bubble_chart::create();
|
|
break;
|
|
case odf_types::chart_class::surface:
|
|
chart = oox_area_chart::create();
|
|
break;
|
|
case odf_types::chart_class::filled_radar:
|
|
chart = oox_radar_chart::create(L"filled");
|
|
break;
|
|
case odf_types::chart_class::gantt:
|
|
default:
|
|
chart = oox_bar_chart::create();
|
|
break;
|
|
}
|
|
charts_.push_back(chart);
|
|
}
|
|
|
|
void oox_plot_area::add_axis(odf_reader::chart::axis& content)
|
|
{
|
|
unsigned int id = content.type_ != 0 ? axis_id_++ : 0;
|
|
oox_axis_content_ptr ax = oox_axis_content::create(id);
|
|
ax->content_ = content;
|
|
|
|
if (content.dimension_ == L"x") axis_.insert(axis_.begin(), ax);
|
|
else axis_.push_back(ax);
|
|
}
|
|
void oox_plot_area::set_no_local_table(bool val)
|
|
{
|
|
no_used_local_tables_ = val;
|
|
}
|
|
void oox_plot_area::set_data_table(odf_reader::chart::simple& content)
|
|
{
|
|
data_table_content_ = content;
|
|
}
|
|
void oox_plot_area::reset_cross_axis()//must be called after all additions
|
|
{
|
|
for (size_t i = 0; i < axis_.size(); i++)
|
|
{
|
|
for (size_t j = 0; j < charts_.size(); j++)
|
|
{
|
|
charts_[j]->add_axis(axis_[i]->get_Id());
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < axis_.size(); i++)
|
|
{
|
|
int curr_id = axis_[i]->get_Id();
|
|
|
|
if (curr_id < 1) continue;
|
|
|
|
for (size_t j = 0; j < axis_.size(); j++)
|
|
{
|
|
if (axis_[j]->get_Id() == curr_id)continue;
|
|
|
|
axis_[j]->add_CrossedId(curr_id);
|
|
}
|
|
}
|
|
}
|
|
void oox_plot_area::oox_serialize_view3D(std::wostream& _Wostream)
|
|
{
|
|
_CP_OPT(std::wstring) strVal;
|
|
_CP_OPT(double) doubleVal;
|
|
_CP_OPT(bool) perspective;
|
|
|
|
odf_reader::GetProperty(properties_, L"transform", strVal);
|
|
odf_reader::GetProperty(properties_, L"perspective", perspective);
|
|
|
|
if (!strVal) return;
|
|
|
|
size_t pos_matrix = strVal->find(L"matrix(");
|
|
|
|
if (pos_matrix == std::wstring::npos) return;
|
|
|
|
size_t pos_matrix_end = strVal->find(L")", pos_matrix);
|
|
if (pos_matrix_end == std::wstring::npos || pos_matrix_end == pos_matrix + 7) return;
|
|
|
|
std::wstring tmp = strVal->substr(pos_matrix + 7, pos_matrix_end - 7 - pos_matrix);
|
|
|
|
std::vector<std::wstring> values;
|
|
|
|
boost::algorithm::split(values, tmp, boost::algorithm::is_any_of(L" "), boost::algorithm::token_compress_on);
|
|
|
|
if (values.size() < 12) return;
|
|
|
|
double left_x = XmlUtils::GetDouble(values[0]);
|
|
double up_x = XmlUtils::GetDouble(values[1]);
|
|
double forward_x = XmlUtils::GetDouble(values[2]);
|
|
double left_y = XmlUtils::GetDouble(values[3]);
|
|
double up_y = XmlUtils::GetDouble(values[4]);
|
|
double forward_y = XmlUtils::GetDouble(values[5]);
|
|
double left_z = XmlUtils::GetDouble(values[6]);
|
|
double up_z = XmlUtils::GetDouble(values[7]);
|
|
double forward_z = XmlUtils::GetDouble(values[8]);
|
|
|
|
const double DEG2RAD = 3.1415926 / 180;
|
|
double sx, sy, sz, cx, cy, cz, theta_x, theta_y, theta_z = 0;
|
|
|
|
sy = forward_x;
|
|
|
|
theta_y = (sy == 0 ? 0 : asin(sy));
|
|
cy = cos(theta_y);
|
|
|
|
theta_y /= DEG2RAD;
|
|
|
|
sx = -forward_y / cy;
|
|
cx = forward_z / cy;
|
|
|
|
theta_x = (sx == 0 ? 0 : asin(sx));
|
|
double theta_x_test = (sx == 0 ? 0 : acos(cx));
|
|
|
|
theta_x /= DEG2RAD;
|
|
|
|
sz = -up_x / cy;
|
|
cz = left_x / cy;
|
|
|
|
theta_z = (sz == 0 ? 0 : asin(sz));
|
|
double theta_z_test = (sz == 0 ? 0 : acos(cz));
|
|
|
|
theta_z /= DEG2RAD;
|
|
|
|
if (this->current_chart_->type_ == CHART_TYPE_RADAR ||
|
|
this->current_chart_->type_ == CHART_TYPE_PIE ||
|
|
this->current_chart_->type_ == CHART_TYPE_DOUGHNUT)
|
|
{
|
|
theta_x += 90;
|
|
}
|
|
else theta_x = (std::abs)(theta_x);
|
|
CP_XML_WRITER(_Wostream)
|
|
{
|
|
CP_XML_NODE(L"c:view3D")
|
|
{
|
|
CP_XML_NODE(L"c:rotX")
|
|
{
|
|
CP_XML_ATTR(L"val", (int)(theta_x + 0.5));
|
|
}
|
|
CP_XML_NODE(L"c:rotY")
|
|
{
|
|
CP_XML_ATTR(L"val", (int)(theta_y + 0.5));
|
|
}
|
|
CP_XML_NODE(L"c:depthPercent")
|
|
{
|
|
CP_XML_ATTR(L"val", 100);
|
|
}
|
|
if (theta_z > 0 || (perspective && *perspective))
|
|
{
|
|
CP_XML_NODE(L"c:rAngAx")
|
|
{
|
|
CP_XML_ATTR(L"val", 0);
|
|
}
|
|
if (theta_z > 0)
|
|
{
|
|
CP_XML_NODE(L"c:perspective")
|
|
{
|
|
CP_XML_ATTR(L"val", (int)(theta_z * 2 + 0.5));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CP_XML_NODE(L"c:rAngAx")
|
|
{
|
|
CP_XML_ATTR(L"val", 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void oox_plot_area::oox_serialize(std::wostream & _Wostream)
|
|
{
|
|
reset_cross_axis();
|
|
|
|
oox_chart_shape shape;
|
|
shape.set(graphic_properties_, fill_);
|
|
|
|
CP_XML_WRITER(_Wostream)
|
|
{
|
|
CP_XML_NODE(L"c:plotArea")
|
|
{
|
|
//CP_XML_NODE(L"c:layout"){}
|
|
bool axisPresent = true;
|
|
|
|
for (size_t i = 0; i < charts_.size(); i++)
|
|
{
|
|
charts_[i]->oox_serialize(CP_XML_STREAM());
|
|
|
|
if (charts_[i]->type_ == CHART_TYPE_PIE ||
|
|
charts_[i]->type_ == CHART_TYPE_DOUGHNUT) axisPresent = false;
|
|
}
|
|
if (axisPresent)
|
|
{
|
|
for (size_t i = 0; i < axis_.size(); i++)
|
|
{
|
|
axis_[i]->oox_serialize(CP_XML_STREAM());
|
|
}
|
|
}
|
|
if (data_table_content_.bEnabled)
|
|
{
|
|
_CP_OPT(bool) boolVal;
|
|
|
|
CP_XML_NODE(L"c:dTable")
|
|
{
|
|
odf_reader::GetProperty(data_table_content_.properties_, L"show-horizontal-border", boolVal);
|
|
if (boolVal)
|
|
{
|
|
CP_XML_NODE(L"c:showHorzBorder")
|
|
{
|
|
CP_XML_ATTR(L"val", *boolVal);
|
|
}
|
|
}
|
|
odf_reader::GetProperty(data_table_content_.properties_, L"show-vertical-border", boolVal);
|
|
if (boolVal)
|
|
{
|
|
CP_XML_NODE(L"c:showVertBorder")
|
|
{
|
|
CP_XML_ATTR(L"val", *boolVal);
|
|
}
|
|
}
|
|
odf_reader::GetProperty(data_table_content_.properties_, L"show-outline", boolVal);
|
|
if (boolVal)
|
|
{
|
|
CP_XML_NODE(L"c:showOutline")
|
|
{
|
|
CP_XML_ATTR(L"val", *boolVal);
|
|
}
|
|
}
|
|
odf_reader::GetProperty(data_table_content_.properties_, L"show-keys", boolVal);
|
|
if (boolVal)
|
|
{
|
|
CP_XML_NODE(L"c:showKeys")
|
|
{
|
|
CP_XML_ATTR(L"val", *boolVal);
|
|
}
|
|
}
|
|
|
|
oox_chart_shape shape_table;
|
|
shape_table.set(data_table_content_.graphic_properties_, data_table_content_.fill_);
|
|
shape_table.oox_serialize(CP_XML_STREAM());
|
|
|
|
if (data_table_content_.text_properties_)
|
|
{
|
|
CP_XML_NODE(L"c:txPr")
|
|
{
|
|
CP_XML_NODE(L"a:bodyPr") {}
|
|
CP_XML_NODE(L"a:lstStyle") {}
|
|
|
|
CP_XML_NODE(L"a:p")
|
|
{
|
|
CP_XML_NODE(L"a:pPr")
|
|
{
|
|
CP_XML_NODE(L"a:defRPr")
|
|
{
|
|
//odf_reader::fonts_container & fonts = context.fontContainer();
|
|
odf_reader::fonts_container fonts;
|
|
data_table_content_.text_properties_->oox_serialize(CP_XML_STREAM(), true, fonts);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
shape.oox_serialize(CP_XML_STREAM());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|