Files
core/OdfFile/Reader/Converter/xlsx_drawing_context.cpp
Elena Subbotina fcdbdff42f fix bug #75006
2025-06-06 15:09:11 +03:00

890 lines
29 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* (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 <boost/algorithm/string.hpp>
#include <iostream>
#include <xml/utils.h>
#include "xlsx_drawing.h"
#include "xlsx_drawings.h"
#include "xlsx_utils.h"
#include "xlsx_drawing_context.h"
#include "xlsx_table_metrics.h"
#include "../Format/draw_common.h"
#include "../../Formulas/formulasconvert.h"
#include "drawing_object_description.h"
#include "../../../OOXML/Base/Unit.h"
namespace cpdoccore {
namespace oox {
class xlsx_drawing_context_handle::Impl
{
public:
Impl(mediaitems_ptr & items) : items_(items), next_drawing_id_(1), next_vml_drawing_id_(1)
{
}
mediaitems_ptr & get_mediaitems() { return items_; }
std::pair<std::wstring, std::wstring> add_drawing_vml(std::wstring const & content, xlsx_drawings_ptr drawings)
{
const std::wstring id = std::to_wstring(next_vml_drawing_id_++);
const std::wstring fileName = std::wstring(L"vmlDrawing") + id + L".vml";
drawings_vml_.push_back(drawing_elm(fileName, content, drawings, typeDefault));
const std::wstring rId = std::wstring(L"rVId") + id;
return std::pair<std::wstring, std::wstring>(fileName, rId);
}
std::pair<std::wstring, std::wstring> add_drawing_xml(std::wstring const & content, xlsx_drawings_ptr drawings, _rels_type const & type_)
{
const std::wstring id = std::to_wstring(next_drawing_id_++);
const std::wstring fileName = std::wstring(L"drawing") + id + L".xml";
drawings_.push_back(drawing_elm(fileName, content, drawings, type_));
const std::wstring rId = std::wstring(L"rDrId") + id;
return std::pair<std::wstring, std::wstring>(fileName, rId);
}
const std::vector<drawing_elm> & content() const
{
return drawings_;
}
const std::vector<drawing_elm> & content_vml() const
{
return drawings_vml_;
}
private:
mediaitems_ptr items_;
std::vector<drawing_elm> drawings_;
std::vector<drawing_elm> drawings_vml_;
size_t next_drawing_id_;
size_t next_vml_drawing_id_;
};
xlsx_drawing_context_handle::xlsx_drawing_context_handle(mediaitems_ptr & items) :
next_rId_(1024), impl_(new xlsx_drawing_context_handle::Impl(items))
{
}
xlsx_drawing_context_handle::~xlsx_drawing_context_handle()
{
}
std::pair<std::wstring, std::wstring> xlsx_drawing_context_handle::add_drawing_xml(std::wstring const & content, xlsx_drawings_ptr drawings, _rels_type const & type_)
{
return impl_->add_drawing_xml(content, drawings, type_);
}
std::pair<std::wstring, std::wstring> xlsx_drawing_context_handle::add_drawing_vml(std::wstring const & content, xlsx_drawings_ptr drawings)
{
return impl_->add_drawing_vml(content, drawings);
}
const std::vector<drawing_elm> & xlsx_drawing_context_handle::content() const
{
return impl_->content();
}
const std::vector<drawing_elm> & xlsx_drawing_context_handle::content_vml() const
{
return impl_->content_vml();
}
class xlsx_drawing_context::Impl
{
public:
Impl(xlsx_drawing_context_handle_ptr & handle) : xlsx_drawings_(xlsx_drawings::create(false)), handle_(handle)
{
current_level_ = &objects_;
use_image_replacement_ = false;
}
xlsx_drawing_context_handle_ptr handle_;
drawing_object_description object_description_;
std::vector<drawing_object_description> objects_;
std::vector<drawing_object_description*> groups_;
std::vector<drawing_object_description> * current_level_;
bool use_image_replacement_;
//-----------------------------------------------------------------------------------
mediaitems_ptr & get_mediaitems() { return handle_->impl_->get_mediaitems(); }
void serialize(std::wostream & strm, const std::wstring & ns, bool local)
{
xlsx_drawings_->serialize(strm, ns, local);
}
void serialize_vml(std::wostream & strm)
{
xlsx_drawings_->serialize_vml(strm);
}
bool empty() const
{
return xlsx_drawings_->empty();
}
bool vml_empty() const
{
return xlsx_drawings_->vml_empty();
}
size_t next_rId()
{
return handle_->next_rId();
}
xlsx_drawings_ptr get_drawings()
{
return xlsx_drawings_;
}
private:
xlsx_drawings_ptr xlsx_drawings_;
};
xlsx_drawing_context::xlsx_drawing_context(xlsx_drawing_context_handle_ptr & h, bool in_text)
: impl_(new xlsx_drawing_context::Impl(h))
{
in_text_ = in_text;
hlinks_size_ = 0;
clear();
}
void xlsx_drawing_context::clear()
{
impl_->object_description_.bInner_ = false;
impl_->object_description_.type_ = typeUnknown;
impl_->object_description_.in_group_ = false;
impl_->object_description_.lined_ = false;
impl_->object_description_.connector_ = false;
impl_->object_description_.xlink_href_ = L"";
impl_->object_description_.name_ = L"";
impl_->object_description_.anchor_ = L"";
impl_->object_description_.anchor_rel_ = anchor_none;
impl_->object_description_.anchor_x_ = 0;
impl_->object_description_.anchor_y_ = 0;
impl_->object_description_.svg_rect_ = boost::none;
impl_->object_description_.additional_.clear();
impl_->object_description_.hlinks_.clear();
impl_->object_description_.action_.clear();
impl_->object_description_.additional_.clear();
impl_->use_image_replacement_ = false;
}
xlsx_drawing_context::~xlsx_drawing_context()
{
}
void xlsx_drawing_context::start_group(std::wstring const & name)
{
start_drawing(name);
impl_->object_description_.type_ = typeGroupShape;
impl_->object_description_.svg_rect_ = _rect();
impl_->object_description_.svg_rect_->x = impl_->object_description_.svg_rect_->y = 0x7fffffff;
impl_->current_level_->push_back(impl_->object_description_);
impl_->groups_.push_back(&impl_->current_level_->back());
impl_->current_level_ = &(impl_->groups_.back()->child_objects_);
clear();
}
void xlsx_drawing_context::end_group()
{
if (impl_->groups_.size() < 1) return;
if (impl_->groups_.back()->svg_rect_)
{
_rect & group_rect = impl_->groups_.back()->svg_rect_.get();
group_rect.cy -= group_rect.y;
group_rect.cx -= group_rect.x;
for (size_t i = 0; i < impl_->groups_.back()->child_objects_.size(); i++)
{
if (!impl_->groups_.back()->child_objects_[i].svg_rect_) continue;
_rect & r = impl_->groups_.back()->child_objects_[i].svg_rect_.get();
r.y -= group_rect.y;
r.x -= group_rect.x;
}
}
if (impl_->groups_.back()->in_group_ && impl_->groups_.back()->svg_rect_)
{
_rect & objct_rect = impl_->groups_.back()->svg_rect_.get();
impl_->groups_.pop_back();
_rect & group_rect = impl_->groups_.back()->svg_rect_.get();
if (group_rect.x > objct_rect.x) group_rect.x = objct_rect.x;
if (group_rect.y > objct_rect.y) group_rect.y = objct_rect.y;
if (group_rect.cx < objct_rect.cx + objct_rect.x) group_rect.cx = objct_rect.cx + objct_rect.x;
if (group_rect.cy < objct_rect.cy + objct_rect.y) group_rect.cy = objct_rect.cy + objct_rect.y;
}
else
impl_->groups_.pop_back();
if (impl_->groups_.size() > 0)
{
impl_->current_level_ = &(impl_->groups_.back()->child_objects_);
}
else
{
impl_->current_level_ = &impl_->objects_;
}
}
bool xlsx_drawing_context::isDefault()
{
return impl_->object_description_.type_ == typeUnknown;
}
void xlsx_drawing_context::start_drawing(std::wstring const & name)
{
impl_->object_description_.name_ = name;
if (false == impl_->groups_.empty())
impl_->object_description_.in_group_ = true;
}
void xlsx_drawing_context::end_drawing()
{
if (impl_->object_description_.in_group_ &&
impl_->object_description_.svg_rect_)
{
_rect & objct_rect = impl_->object_description_.svg_rect_.get();
_rect & group_rect = impl_->groups_.back()->svg_rect_.get();
if (group_rect.x > objct_rect.x) group_rect.x = objct_rect.x;
if (group_rect.y > objct_rect.y) group_rect.y = objct_rect.y;
if (group_rect.cx < objct_rect.cx + objct_rect.x) group_rect.cx = objct_rect.cx + objct_rect.x;
if (group_rect.cy < objct_rect.cy + objct_rect.y) group_rect.cy = objct_rect.cy + objct_rect.y;
}
}
void xlsx_drawing_context::start_shape(int type)
{
impl_->object_description_.type_ = typeShape;
impl_->object_description_.shape_type_ = type; //2,3...
}
void xlsx_drawing_context::end_shape()
{
impl_->current_level_->push_back(impl_->object_description_);
clear();
}
void xlsx_drawing_context::start_comment(int base_col, int base_row)
{
impl_->object_description_.type_ = typeComment;
impl_->object_description_.shape_type_ = 0x0019; // OBJ_Note object type for vml
set_property(odf_reader::_property(L"base_col", base_col));
set_property(odf_reader::_property(L"base_row", base_row));
}
void xlsx_drawing_context::end_comment()
{
impl_->current_level_->push_back(impl_->object_description_);
}
void xlsx_drawing_context::start_control(const std::wstring & ctrlPropId, int type)
{
impl_->object_description_.type_ = typeControl;
impl_->object_description_.shape_type_ = type; // object type for vml
impl_->object_description_.xlink_href_ = ctrlPropId;
}
void xlsx_drawing_context::end_control()
{
impl_->current_level_->push_back(impl_->object_description_);
clear();
}
void xlsx_drawing_context::set_use_image_replacement()
{
impl_->use_image_replacement_ = true;
}
void xlsx_drawing_context::set_text_box()
{
impl_->object_description_.type_ = typeShape;
impl_->object_description_.shape_type_ = 2; //2,3...
}
void xlsx_drawing_context::set_ole_object(const std::wstring & path, const std::wstring & progId)
{
impl_->object_description_.type_ = typeOleObject;
impl_->object_description_.xlink_href_ = path;
impl_->object_description_.descriptor_ = progId;
}
void xlsx_drawing_context::set_ms_object(const std::wstring & path, const std::wstring & progId)
{
impl_->object_description_.type_ = typeMsObject;
impl_->object_description_.xlink_href_ = path;
impl_->object_description_.descriptor_ = progId;
}
void xlsx_drawing_context::set_image(const std::wstring & path)
{
int pos_replaicement = path.find(L"ObjectReplacements");
if (pos_replaicement >= 0)
{
if (path.length() - (pos_replaicement + 18) < 2)
return; //object without image
}
if (impl_->object_description_.type_ == typeUnknown)
{
impl_->object_description_.type_ = typeImage;
impl_->object_description_.xlink_href_ = path;
}
else if (impl_->use_image_replacement_)
{
impl_->object_description_.fill_.type = 2;
impl_->object_description_.fill_.bitmap = oox::oox_bitmap_fill::create();
impl_->object_description_.fill_.bitmap->xlink_href_ = path;
}
}
bool xlsx_drawing_context::start_frame()
{
if (impl_->object_description_.type_ != typeUnknown)
impl_->object_description_.bInner_ = true;
return impl_->object_description_.bInner_;
}
void xlsx_drawing_context::end_frame()
{
if (impl_->object_description_.bInner_)
impl_->object_description_.bInner_ = false;
else
{
impl_->current_level_->push_back(impl_->object_description_);
}
clear();
}
void xlsx_drawing_context::set_chart(const std::wstring & path)
{
impl_->object_description_.type_ = typeChart;
impl_->object_description_.xlink_href_ = path;
}
void xlsx_drawing_context::set_rect(double width_pt, double height_pt, double x_pt, double y_pt)
{
impl_->object_description_.svg_rect_ = _rect(width_pt, height_pt, x_pt, y_pt);
}
void xlsx_drawing_context::set_translate(double x_pt, double y_pt)
{
if (impl_->object_description_.svg_rect_)
{
_rect & r = impl_->object_description_.svg_rect_.get();
r.x += x_pt;
r.y += y_pt;
}
}
void xlsx_drawing_context::set_rotate(double angle, bool translate)
{
set_property(odf_reader::_property(L"svg:rotate", angle));
if (impl_->object_description_.svg_rect_ && translate)
{
_rect &r = impl_->object_description_.svg_rect_.get();
double new_x = (r.cx / 2 * cos(-angle) - r.cy / 2 * sin(-angle) ) - r.cx / 2;
double new_y = (r.cx / 2 * sin(-angle) + r.cy / 2 * cos(-angle) ) - r.cy / 2;
r.x += new_x;
r.y += new_y;
}
}
void xlsx_drawing_context::set_scale(double cx_pt, double cy_pt)
{
if (impl_->object_description_.svg_rect_)
{
_rect & r = impl_->object_description_.svg_rect_.get();
r.x *= cx_pt;
r.y *= cy_pt;
}
}
void xlsx_drawing_context::set_rel_anchor(_INT32 owner_cx, _INT32 owner_cy)
{
impl_->object_description_.owner_cx_ = owner_cx;
impl_->object_description_.owner_cy_ = owner_cy;
}
void xlsx_drawing_context::set_anchor_end(std::wstring anchor, double x_pt, double y_pt, bool group)
{
if (group)
{
impl_->groups_.back()->anchor_rel_ = anchor_end;
impl_->groups_.back()->anchor_ = anchor;
impl_->groups_.back()->anchor_x_ = x_pt;
impl_->groups_.back()->anchor_y_ = y_pt;
}
else
{
impl_->object_description_.anchor_rel_ = anchor_end;
impl_->object_description_.anchor_ = anchor;
impl_->object_description_.anchor_x_ = x_pt;
impl_->object_description_.anchor_y_ = y_pt;
}
}
void xlsx_drawing_context::set_anchor_start(std::wstring anchor, double x_pt, double y_pt, bool group)
{
if (group)
{
impl_->groups_.back()->anchor_rel_ = anchor_start;
impl_->groups_.back()->anchor_ = anchor;
impl_->groups_.back()->anchor_x_ = x_pt;
impl_->groups_.back()->anchor_y_ = y_pt;
}
else
{
impl_->object_description_.anchor_rel_ = anchor_start;
impl_->object_description_.anchor_ = anchor;
impl_->object_description_.anchor_x_ = x_pt;
impl_->object_description_.anchor_y_ = y_pt;
}
}
void xlsx_drawing_context::set_property(odf_reader::_property p)
{
impl_->object_description_.additional_.push_back(p);
}
std::vector<odf_reader::_property> & xlsx_drawing_context::get_properties()
{
return impl_->object_description_.additional_;
}
void xlsx_drawing_context::set_fill(_oox_fill & fill)
{
impl_->object_description_.fill_= fill;
}
std::wstring xlsx_drawing_context::add_hyperlink(std::wstring const & href)
{
++hlinks_size_;
std::wstring hId = L"hId" + std::to_wstring(hlinks_size_);
std::wstring href_correct = XmlUtils::EncodeXmlString(href);
XmlUtils::replace_all( href_correct, L" .", L".");//1 (130).odt
//корректность написания ссылки важна для ms office и не важна для open office ->
//todooo
_hlink_desc desc = {hId, href_correct};
impl_->object_description_.hlinks_.push_back(desc);
return hId;
}
bool xlsx_drawing_context::empty() const
{
return impl_->empty();
}
bool xlsx_drawing_context::vml_empty() const
{
return impl_->vml_empty();
}
void xlsx_drawing_context::process_common_properties(drawing_object_description & obj, _xlsx_drawing & drawing, xlsx_table_metrics & table_metrics)
{
if (obj.anchor_rel_ == anchor_none)
{
if (obj.owner_cx_ && obj.owner_cy_)
{
drawing.type_anchor = 3; // relative
drawing.owner_cx_ = obj.owner_cx_;
drawing.owner_cy_ = obj.owner_cy_;
}
else
drawing.type_anchor = 2; // absolute
}
if (drawing.type_anchor == 1 || obj.type_ == typeMsObject || obj.type_ == typeOleObject || obj.type_ == typeControl)
{
xlsx_table_position from, to;
process_position_properties (obj, table_metrics, from, to, obj.anchor_rel_ == anchor_end);
drawing.from_.type = xlsx_drawing_position::from;
drawing.from_.position.col = from.col;
drawing.from_.position.colOff = static_cast<size_t>(odf_types::length(from.colOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.from_.position.row = from.row;
drawing.from_.position.rowOff = static_cast<size_t>(odf_types::length(from.rowOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.to_.type = xlsx_drawing_position::to;
drawing.to_.position.col = to.col;
drawing.to_.position.colOff = static_cast<size_t>(odf_types::length(to.colOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.to_.position.row = to.row;
drawing.to_.position.rowOff = static_cast<size_t>(odf_types::length(to.rowOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
}
if (obj.svg_rect_)
{
_rect & r = obj.svg_rect_.get();
//todooo непонятно что делать с отрицательными значениями
_INT32 val = 0;
val = (_INT32) (0.5 + odf_types::length(obj.svg_rect_->x, odf_types::length::pt).get_value_unit(odf_types::length::emu));
if (val >= 0) drawing.x = val;
val = (_INT32) (0.5 + odf_types::length(obj.svg_rect_->y, odf_types::length::pt).get_value_unit(odf_types::length::emu));
if (val >= 0) drawing.y = val;
val = (_INT32) (0.5 + odf_types::length(obj.svg_rect_->cx, odf_types::length::pt).get_value_unit(odf_types::length::emu));
if (val >= 0) drawing.cx = val;
val = (_INT32) (0.5 + odf_types::length(obj.svg_rect_->cy, odf_types::length::pt).get_value_unit(odf_types::length::emu));
if (val >= 0) drawing.cy = val;
}
drawing.additional = obj.additional_;
drawing.hlinks = obj.hlinks_;
drawing.action = obj.action_;
}
void xlsx_drawing_context::process_position_properties(drawing_object_description & obj, xlsx_table_metrics & table_metrics,xlsx_table_position & from,xlsx_table_position & to, bool byEnd)
{
size_t column_anchor = 0, row_anchor = 0;
std::vector<std::wstring> distance;
boost::algorithm::split(distance, obj.anchor_, boost::algorithm::is_any_of(L" ."), boost::algorithm::token_compress_on);
double x = 0, y = 0, cx = 0, cy = 0;
if (obj.svg_rect_)
{
x = obj.svg_rect_->x;
y = obj.svg_rect_->y;
cx = obj.svg_rect_->cx;
cy = obj.svg_rect_->cy;
}
to = table_metrics.calc(x + cx, y + cy);
from = table_metrics.calc(x, y);
if (!distance.empty() && !obj.anchor_.empty())
{
int ind_cell = distance.size() - 1;
if (false == getCellAddressInv(distance[ind_cell], column_anchor, row_anchor)) return;
xlsx_table_position pos_anchor = table_metrics.calc(column_anchor, row_anchor, obj.anchor_x_, obj.anchor_y_);
table_metrics.update_pt(column_anchor, row_anchor, obj.anchor_x_, obj.anchor_y_);
if (byEnd)
{
to = pos_anchor;
x = obj.anchor_x_ - cx;
y = obj.anchor_y_ - cy;
if (x < 0) x = 0;
if (y < 0) y = 0; // calcul dun MS.ods
from = table_metrics.calc(x, y);
}
else
{
from = pos_anchor;
x = obj.anchor_x_ + cx;
y = obj.anchor_y_ + cy;
to = table_metrics.calc(x, y);
}
if (obj.svg_rect_)
{
_rect r_old = obj.svg_rect_.get();
obj.svg_rect_= _rect (cx, cy, x, y);
}
}
}
void xlsx_drawing_context::process_image(drawing_object_description & obj, _xlsx_drawing & drawing, xlsx_drawings_ptr xlsx_drawings_)
{
if (!drawing.fill.bitmap)
{
drawing.fill.bitmap = oox_bitmap_fill::create();
drawing.fill.type = 2;
}
_CP_OPT(std::wstring) sTextContent;
GetProperty(obj.additional_, L"text-content", sTextContent);
GetProperty(obj.additional_, L"color-mode", drawing.fill.bitmap->color_mode);
GetProperty(obj.additional_, L"luminance", drawing.fill.bitmap->luminance);
GetProperty(obj.additional_, L"contrast", drawing.fill.bitmap->contrast);
if (sTextContent)//в ms office на картинке нельзя сделать надпись - меняем тип на рект с заливкой картинкой
{
drawing.type = typeShape;
drawing.sub_type = 2;//rect
}
std::wstring fileName = odf_packet_path_ + FILE_SEPARATOR_STR + obj.xlink_href_;
_image_file_::GetResolution(fileName.c_str(), drawing.fill.bitmap->width, drawing.fill.bitmap->height, impl_->get_mediaitems()->applicationFonts());
if (drawing.fill.bitmap->width && drawing.fill.bitmap->height)
{
drawing.fill.bitmap->bCrop = odf_reader::parse_clipping(drawing.fill.clipping, *drawing.fill.bitmap->width, *drawing.fill.bitmap->height, drawing.fill.bitmap->cropRect);
if (drawing.fill.bitmap->sx_pt && drawing.fill.bitmap->sy_pt)
{
drawing.fill.bitmap->sx = (*drawing.fill.bitmap->sx_pt * 100. / *drawing.fill.bitmap->width) * 4 / 3;
drawing.fill.bitmap->sy = (*drawing.fill.bitmap->sy_pt * 100. / *drawing.fill.bitmap->height) * 4 / 3;
}
}
if (!drawing.fill.bitmap->bTile && drawing.fill.bitmap->sx && drawing.fill.bitmap->sy)
{
drawing.fill.bitmap->bStretch = true;
}
std::wstring ref;/// это ссылка на выходной внешний объект
bool isMediaInternal = false;
drawing.fill.bitmap->rId = impl_->get_mediaitems()->add_or_find(obj.xlink_href_, typeImage, isMediaInternal, ref, oox::document_place);
if (drawing.type == typeShape)
{
impl_->get_drawings()->add(isMediaInternal, drawing.fill.bitmap->rId, ref, typeImage, false, false);//собственно это не объект, а доп рел и ref объекта
isMediaInternal=true;
std::wstring rId = impl_->get_mediaitems()->add_or_find(L"", typeShape, isMediaInternal, ref, oox::document_place);
xlsx_drawings_->add(drawing, isMediaInternal, rId, ref, typeShape);//объект
}
else
{
xlsx_drawings_->add(drawing, isMediaInternal, drawing.fill.bitmap->rId , ref, typeImage);//объект
if (drawing.inGroup)
impl_->get_drawings()->add(isMediaInternal, drawing.fill.bitmap->rId, ref, obj.type_, false, false); // не объект
}
}
void xlsx_drawing_context::process_chart(drawing_object_description & obj,_xlsx_drawing & drawing, xlsx_drawings_ptr xlsx_drawings_)
{
std::wstring ref;
bool isMediaInternal = true;
drawing.objectId = impl_->get_mediaitems()->add_or_find(obj.xlink_href_, obj.type_, isMediaInternal, ref, oox::document_place);
xlsx_drawings_->add(drawing, isMediaInternal, drawing.objectId, ref, obj.type_);
if (drawing.inGroup)
impl_->get_drawings()->add(isMediaInternal, drawing.objectId, ref, obj.type_, false, false); // не объект
}
void xlsx_drawing_context::process_object(drawing_object_description & obj, xlsx_table_metrics & table_metrics, _xlsx_drawing & drawing, xlsx_drawings_ptr xlsx_drawings_)
{
std::wstring ref;
bool isMediaInternal = true;
if (drawing.type_anchor == 2) // absolute
{
//пересчет нужен
xlsx_table_position from, to;
process_position_properties (obj, table_metrics, from, to);
drawing.from_.type = xlsx_drawing_position::from;
drawing.from_.position.col = from.col;
drawing.from_.position.colOff = static_cast<size_t>(odf_types::length(from.colOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.from_.position.row = from.row;
drawing.from_.position.rowOff = static_cast<size_t>(odf_types::length(from.rowOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.to_.type = xlsx_drawing_position::to;
drawing.to_.position.col = to.col;
drawing.to_.position.colOff = static_cast<size_t>(odf_types::length(to.colOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
drawing.to_.position.row = to.row;
drawing.to_.position.rowOff = static_cast<size_t>(odf_types::length(to.rowOff, odf_types::length::pt).get_value_unit(odf_types::length::emu));
}
if (obj.type_ == typeControl || obj.type_ == typeComment)
{
drawing.objectId = obj.xlink_href_;
xlsx_drawings_->add(drawing, isMediaInternal, drawing.objectId, ref, obj.type_, false);
}
else
{
drawing.objectId = impl_->get_mediaitems()->add_or_find(obj.xlink_href_, obj.type_, isMediaInternal, ref, oox::document_place);
drawing.objectProgId = obj.descriptor_;
xlsx_drawings_->add(drawing, isMediaInternal, drawing.objectId, ref, obj.type_, true);
}
if (drawing.inGroup)
{// не объекты
if (obj.type_ == typeControl || obj.type_ == typeComment)
impl_->get_drawings()->add(isMediaInternal, drawing.objectId, ref, obj.type_, false, false);
else
impl_->get_drawings()->add(isMediaInternal, drawing.objectId, ref, obj.type_, true, false);
}
}
void xlsx_drawing_context::process_shape(drawing_object_description & obj,_xlsx_drawing & drawing, xlsx_drawings_ptr xlsx_drawings_)
{
std::wstring ref;
bool isMediaInternal = true;
std::wstring rId = impl_->get_mediaitems()->add_or_find(L"", obj.type_, isMediaInternal, ref, oox::document_place);
xlsx_drawings_->add(drawing, isMediaInternal, rId, ref, obj.type_);
}
void xlsx_drawing_context::process_group(drawing_object_description & obj, xlsx_table_metrics & table_metrics, _xlsx_drawing & drawing, xlsx_drawings_ptr xlsx_drawings_)
{
xlsx_drawings_ptr xlsx_drawings_child(xlsx_drawings::create(true));
process_group_objects( obj.child_objects_, table_metrics, xlsx_drawings_child);
drawing.childs_ = xlsx_drawings_child->get();
std::wstringstream strm;
xlsx_drawings_child->serialize(strm, L"xdr", in_text_);
drawing.content_group_ = strm.str();
//-----------------------------------------------------------------------------------------------
std::wstring ref;
bool isMediaInternal = true;
std::wstring rId = impl_->get_mediaitems()->add_or_find(L"", obj.type_, isMediaInternal, ref, oox::document_place);
xlsx_drawings_->add(drawing, isMediaInternal, rId, ref, obj.type_);
}
void xlsx_drawing_context::process_objects(xlsx_table_metrics & table_metrics)
{
process_group_objects(impl_->objects_, table_metrics, impl_->get_drawings());
}
void xlsx_drawing_context::process_group_objects(std::vector<drawing_object_description> objects, xlsx_table_metrics & table_metrics, xlsx_drawings_ptr xlsx_drawings_)
{
for (size_t i = 0 ; i < objects.size(); i++)
{
drawing_object_description & obj = objects[i];
_xlsx_drawing drawing =_xlsx_drawing();
drawing.type = obj.type_;
drawing.name = obj.name_;
drawing.fill = obj.fill_;
drawing.inGroup = obj.in_group_;
drawing.id = impl_->next_rId();
drawing.lined = obj.lined_;
drawing.connector = obj.connector_;
drawing.sub_type = obj.shape_type_;
if (drawing.fill.bitmap)
{
std::wstring ref;
bool isMediaInternal = true;
drawing.fill.bitmap->rId = impl_->get_mediaitems()->add_or_find(drawing.fill.bitmap->xlink_href_, typeImage, isMediaInternal, ref, oox::document_place);
bool in_sheet = (obj.type_== typeOleObject || obj.type_== typeMsObject) ? true : false;
impl_->get_drawings()->add(isMediaInternal, drawing.fill.bitmap->rId, ref, typeImage, in_sheet, false);//собственно это не объект, а доп рел и ref объекта
//object dumps in sheet rels !!
}
process_common_properties(obj, drawing, table_metrics);
switch(obj.type_)
{
case typeChart: process_chart ( obj, drawing, xlsx_drawings_); break;
case typeImage: process_image ( obj, drawing, xlsx_drawings_); break;
case typeShape: process_shape ( obj, drawing, xlsx_drawings_); break;
case typeGroupShape: process_group ( obj, table_metrics, drawing, xlsx_drawings_); break;
case typeMsObject:
case typeOleObject:
case typeControl:
case typeComment: process_object ( obj, table_metrics, drawing, xlsx_drawings_); break;
}
}
}
void xlsx_drawing_context::serialize(std::wostream & strm, const std::wstring& ns, bool local)
{
impl_->serialize(strm, ns, local);
}
void xlsx_drawing_context::serialize_vml(std::wostream & strm)
{
impl_->serialize_vml(strm);
}
xlsx_drawings_ptr xlsx_drawing_context::get_drawings()
{
return impl_->get_drawings();
}
void xlsx_drawing_context::start_action(std::wstring action)
{
impl_->object_description_.action_.enabled = true;
}
void xlsx_drawing_context::set_link(std::wstring link, _rels_type typeRels)
{//hyprelinks only
++hlinks_size_;
std::wstring hId = L"hId" + std::to_wstring(hlinks_size_);
link = XmlUtils::EncodeXmlString(link);
if (typeRels == typeHyperlink)
XmlUtils::replace_all( link, L" .", L"."); //1 (130).odt
impl_->object_description_.action_.hId = hId;
impl_->object_description_.action_.hRef = link;
impl_->object_description_.action_.typeRels = typeRels;
}
void xlsx_drawing_context::end_action()
{
}
void xlsx_drawing_context::set_is_line_shape(bool val)
{
impl_->object_description_.lined_ = val;
}
void xlsx_drawing_context::set_is_connector_shape(bool val)
{
impl_->object_description_.connector_ = val;
}
}
}