Files
core/OdfFile/Reader/Format/draw_common.cpp

894 lines
30 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 <ostream>
#include <sstream>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>
#include "odf_document.h"
#include "serialize_elements.h"
#include "draw_common.h"
#include "style_paragraph_properties.h"
#include "../../DataTypes/length.h"
#include "../../DataTypes/borderstyle.h"
#include "odfcontext.h"
/////////////////////////////////////////////////////////////////////////////////
#include "../../../DesktopEditor/raster/BgraFrame.h"
#include "../../../DesktopEditor/graphics/pro/Image.h"
#include "../../../OOXML/Base/Unit.h"
namespace _image_file_
{
bool GetResolution(const wchar_t* fileName, int & Width, int &Height, NSFonts::IApplicationFonts* appFonts)
{
CBgraFrame image;
MetaFile::IMetaFile* meta_file = MetaFile::Create(appFonts);
bool bRet = false;
if ( appFonts && meta_file->LoadFromFile(fileName))
{
double dX = 0, dY = 0, dW = 0, dH = 0;
meta_file->GetBounds(&dX, &dY, &dW, &dH);
Width = dW;
Height = dH;
}
else if ( image.OpenFile(fileName, 0 ))
{
Width = image.get_Width();
Height = image.get_Height();
bRet = true;
}
RELEASEOBJECT(meta_file);
return bRet;
}
void GenerateZeroImage(const std::wstring & fileName)
{
NSFile::CFileBinary file;
if (file.CreateFileW(fileName))
{
BYTE pData[149] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x08, 0x03, 0x00, 0x00, 0x01, 0x5f, 0xcc, 0x04, 0x2d, 0x00, 0x00, 0x00,
0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, 0x00, 0x04,
0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00,
0x00, 0x06, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x67,
0xb9, 0xcf, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0xff, 0x00, 0xe5, 0xb7,
0x30, 0x4a, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x12, 0x74,
0x00, 0x00, 0x12, 0x74, 0x01, 0xde, 0x66, 0x1f, 0x78, 0x00, 0x00, 0x00, 0x0a, 0x49,
0x44, 0x41, 0x54, 0x18, 0x57, 0x63, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0xa3,
0xda, 0x3d, 0x94, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};
file.WriteFile(pData, 149);
file.CloseFile();
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace cpdoccore {
using namespace odf_types;
namespace odf_reader {
int get_value_emu(const _CP_OPT(length) & len)
{
return static_cast<int>(len.get_value_or( length(0, length::pt) ).get_value_unit( length::emu ));
}
int get_value_emu(double pt)
{
return static_cast<int>((pt* 360000 * 2.54) / 72);
}
bool parse_clipping(std::wstring strClipping,std::wstring fileName, double_4 & clip_rect, NSFonts::IApplicationFonts *appFonts)
{
memset(clip_rect, 0, 4*sizeof(double));
if (strClipping.empty() || fileName.empty()) return false;
//<top>, <right>, <bottom>, <left> - http://www.w3.org/TR/2001/REC-xsl-20011015/xslspec.html#clip
bool bEnableCrop = false;
std::vector<std::wstring> Points;
std::vector<length> Points_pt;
boost::algorithm::split(Points, strClipping, boost::algorithm::is_any_of(L" ,"), boost::algorithm::token_compress_on);
for (size_t i = 0; i < Points.size(); i++)
{
Points_pt.push_back(length::parse(Points[i]) );
if (Points_pt.back().get_value() > 0.00001) bEnableCrop = true;
}
if (!bEnableCrop) return false;
int fileWidth = 0,fileHeight = 0;
if (!_image_file_::GetResolution(fileName.data(), fileWidth, fileHeight, appFonts) || fileWidth < 1 || fileHeight < 1) return false;
if (Points_pt.size() > 3)//если другое количество точек .. попозже
{
float dpi_ = 96.;
clip_rect[0] = dpi_ * Points_pt[3].get_value_unit(length::inch);
clip_rect[1] = dpi_ * Points_pt[0].get_value_unit(length::inch);
clip_rect[2] = dpi_ * Points_pt[1].get_value_unit(length::inch);
clip_rect[3] = dpi_ * Points_pt[2].get_value_unit(length::inch);
// в проценты
clip_rect[0] = clip_rect[0]*100/fileWidth;
clip_rect[2] = clip_rect[2]*100/fileWidth;
clip_rect[1] = clip_rect[1]*100/fileHeight;
clip_rect[3] = clip_rect[3]*100/fileHeight;
if (clip_rect[0] < 0.01 && clip_rect[1] < 0.01 && clip_rect[2] < 0.01 && clip_rect[3] < 0.01)
return false;
return true;
}
return false;
}
_CP_OPT(border_widths) GetBorderLineWidths(const graphic_format_properties_ptr & graphicProperties, BorderSide borderSide)
{
_CP_OPT(border_widths) widths;
if (graphicProperties)
{
widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_;
if (widths)
return widths;
switch (borderSide)
{
case sideTop: widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_top_; break;
case sideBottom: widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_bottom_; break;
case sideLeft: widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_left_; break;
case sideRight: widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_right_; break;
default:
widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_top_;
if (widths)
break;
else
widths = graphicProperties->common_border_line_width_attlist_.style_border_line_width_bottom_;
}
}
return widths;
}
_CP_OPT(length) GetConsistentBorderValue(const graphic_format_properties_ptr & graphicProperties, const border_style & borderStyle, BorderSide borderSide)
{
if ((borderStyle.get_style() == border_style::double_))
{
_CP_OPT(border_widths) borderWidths = GetBorderLineWidths(graphicProperties, borderSide);
if (borderWidths)
return length(borderWidths->get_summ_unit( length::pt), length::pt);
}
else
{
if (borderStyle.initialized())
{
if (borderStyle.is_none())
return _CP_OPT(length)();
else
return borderStyle.get_length();
}
}
return _CP_OPT(length)();
}
int GetMargin(const graphic_format_properties_ptr & graphicProperties, BorderSide borderSide)//emu
{
if (!graphicProperties) return 0;
int margin = 0;
_CP_OPT(length_or_percent) marginVal;
switch(borderSide)
{
case sideTop: marginVal = graphicProperties->common_vertical_margin_attlist_.fo_margin_top_; break;
case sideBottom: marginVal = graphicProperties->common_vertical_margin_attlist_.fo_margin_bottom_; break;
case sideLeft: marginVal = graphicProperties->common_horizontal_margin_attlist_.fo_margin_left_; break;
case sideRight: marginVal = graphicProperties->common_horizontal_margin_attlist_.fo_margin_right_; break;
}
if (marginVal && marginVal->get_type() == length_or_percent::Length)
{
margin = get_value_emu(marginVal->get_length());
}
return margin;
}
int Compute_BorderWidth(const graphic_format_properties_ptr & graphicProperties, BorderSide borderSide)
{
if (!graphicProperties)
return 0;
_CP_OPT(border_style) borderValue;
_CP_OPT(length) lengthValue;
switch(borderSide)
{
case sideTop: borderValue = graphicProperties->common_border_attlist_.fo_border_top_; break;
case sideBottom: borderValue = graphicProperties->common_border_attlist_.fo_border_bottom_; break;
case sideLeft: borderValue = graphicProperties->common_border_attlist_.fo_border_left_; break;
case sideRight: borderValue = graphicProperties->common_border_attlist_.fo_border_right_; break;
}
if (!borderValue)
borderValue = graphicProperties->common_border_attlist_.fo_border_;
if (borderValue)
lengthValue = GetConsistentBorderValue(graphicProperties, *borderValue, borderSide);
return get_value_emu(lengthValue);
}
void Compute_HatchFill(draw_hatch * image_style,oox::oox_hatch_fill_ptr fill)
{
int style =0;
if (image_style->draw_style_)style = image_style->draw_style_->get_type();
int angle = image_style->draw_rotation_ ? (int)(0.5 + *image_style->draw_rotation_/10.) : 0;
if (image_style->draw_color_)fill->color_ref = image_style->draw_color_->get_hex_value();
double size =0;
if (image_style->draw_distance_)size = (image_style->draw_distance_->get_value_unit(length::cm));
switch(style)
{
case hatch_style::single:
if (angle == 0 || angle == 180) fill->preset = L"dkHorz";
else if (angle == 90 || angle == 270) fill->preset = L"dkVert";
else if ((angle>180 && angle <270)
|| (angle>0 && angle <90)) fill->preset = L"dkUpDiag";
else fill->preset = L"dkDnDiag";
break;
case hatch_style::doublee:
if (angle ==0 || angle == 90 || angle== 180 || angle == 270)
{
if (size > 0.2) fill->preset = L"lgGrid";
else fill->preset = L"smGrid";
}
else fill->preset = L"openDmnd";
break;
case hatch_style::triple:
fill->preset = L"pct5";
break;
}
}
void Compute_GradientFill(draw_gradient* gradient_style, oox::oox_gradient_fill_ptr fill)
{
int style = 0;
if (gradient_style->draw_style_)
style = gradient_style->draw_style_->get_type();
if (gradient_style->draw_angle_)
{
double angle = std::fmod(gradient_style->draw_angle_->get_value(), 360.0);
if (angle < 0)
angle += 360.0;
fill->angle = -angle + 90;
}
if (fill->angle < 0)
{
int fullRotations = std::ceil(-fill->angle / 360.0f);
fill->angle += 360 * fullRotations;
}
for (size_t i = 0; i < gradient_style->content_.size(); ++i)
{
loext_gradient_stop* gradient_stop = dynamic_cast<loext_gradient_stop*>(gradient_style->content_[i].get());
if (gradient_stop)
{
if (fill->colors.size() <= i) fill->colors.emplace_back();
if (gradient_stop->color_value_)
fill->colors[i].color_ref = gradient_stop->color_value_->get_hex_value();
if (gradient_stop->svg_offset_)
fill->colors[i].pos = *gradient_stop->svg_offset_ * 100;
}
}
fill->style = 0;
if (style == gradient_style::radial ||
style == gradient_style::ellipsoid) fill->style = 2;
else if (style == gradient_style::square) fill->style = 1;
else if (style == gradient_style::rectangular) fill->style = 3;
if (fill->colors.empty())
{
oox::oox_gradient_fill::_color_position point = {};
switch (style)
{
case gradient_style::linear:
{
point.pos = 0;
if (gradient_style->draw_start_color_) point.color_ref = gradient_style->draw_start_color_->get_hex_value();
//if (gradient_style->draw_start_intensity_) point.opacity = gradient_style->draw_start_intensity_->get_value();
fill->colors.push_back(point);
point.pos = 100;
if (gradient_style->draw_end_color_) point.color_ref = gradient_style->draw_end_color_->get_hex_value();
if (gradient_style->draw_end_intensity_) point.opacity = gradient_style->draw_end_intensity_->get_value();
fill->colors.push_back(point);
}break;
case gradient_style::axial:
{
point.pos = 0;
if (gradient_style->draw_end_color_) point.color_ref = gradient_style->draw_end_color_->get_hex_value();
//if (gradient_style->draw_end_intensity_) point.opacity = gradient_style->draw_end_intensity_->get_value();
fill->colors.push_back(point);
point.pos = 50;
if (gradient_style->draw_start_color_) point.color_ref = gradient_style->draw_start_color_->get_hex_value();
if (gradient_style->draw_start_intensity_) point.opacity = gradient_style->draw_start_intensity_->get_value();
fill->colors.push_back(point);
point.pos = 100;
if (gradient_style->draw_end_color_) point.color_ref = gradient_style->draw_end_color_->get_hex_value();
//if (gradient_style->draw_end_intensity_) point.opacity = gradient_style->draw_end_intensity_->get_value();
fill->colors.push_back(point);
}break;
case gradient_style::radial:
case gradient_style::ellipsoid:
case gradient_style::square:
case gradient_style::rectangular:
{
point.pos = 0;
if (gradient_style->draw_start_color_) point.color_ref = gradient_style->draw_end_color_->get_hex_value();
//if (gradient_style->draw_start_intensity_) point.opacity = gradient_style->draw_end_intensity_->get_value();
fill->colors.push_back(point);
point.pos = 100;
if (gradient_style->draw_end_color_) point.color_ref = gradient_style->draw_start_color_->get_hex_value();
//if (gradient_style->draw_end_intensity_) point.opacity = gradient_style->draw_start_intensity_->get_value();
fill->colors.push_back(point);
}break;
}
}
if (fill->style >= 1)
{
fill->rect[0] = fill->rect[1] = 0;
fill->rect[2] = fill->rect[3] = 100;
if (gradient_style->draw_cx_)
{
fill->rect[0] = 100 - gradient_style->draw_cx_->get_value();
fill->rect[2] = gradient_style->draw_cx_->get_value();
}
if (gradient_style->draw_cy_)
{
fill->rect[1] = 100 - gradient_style->draw_cy_->get_value();
fill->rect[3] = gradient_style->draw_cy_->get_value();
}
}
}
void Compute_GraphicFill(const common_draw_fill_attlist & props, const office_element_ptr & style_image, odf_document* document, oox::_oox_fill & fill, bool txbx, bool reset_fill)
{
styles_lite_container& styles = document->odf_context().drawStyles();
if (fill.type < 1 && reset_fill) fill.type = 0;
if (props.draw_opacity_)
{
fill.opacity = props.draw_opacity_->get_value();
}
if (props.draw_opacity_name_)
{
const std::wstring style_name = L"opacity:" + *props.draw_opacity_name_;
if (office_element_ptr style = styles.find_by_style_name(style_name))
{
if (draw_opacity * opacity_style = dynamic_cast<draw_opacity *>(style.get()))
{
if (opacity_style->draw_start_ && opacity_style->draw_end_ || opacity_style->content_.size() > 1)
{
fill.gradient = oox::oox_gradient_fill::create();
fill.type = 3; //?? градиентная прозрачность на картинку
for (size_t i = 0; i < opacity_style->content_.size(); ++i)
{
loext_opacity_stop* opacity_stop = dynamic_cast<loext_opacity_stop*>(opacity_style->content_[i].get());
fill.gradient->colors.emplace_back();
fill.gradient->colors.back().opacity = 100 * opacity_stop->stop_opacity_.get_value_or(0);
fill.gradient->colors.back().pos = opacity_stop->svg_offset_.get_value_or(0) * 100;
}
}
else if (opacity_style->draw_start_) fill.opacity = opacity_style->draw_start_->get_value();
else if (opacity_style->draw_end_) fill.opacity = opacity_style->draw_end_->get_value();
}
}
}
if (props.draw_image_opacity_)
{
fill.image_opacity = props.draw_image_opacity_->get_value();
}
////////////////////////////////////////////////////////////
if (props.draw_fill_color_)
{
fill.solid = oox::oox_solid_fill::create();
fill.solid->color = props.draw_fill_color_->get_hex_value();
if (fill.type <= 0 && !txbx ) fill.type = 1; //в этом случае тип может и не быть задан явно
if (fill.gradient)
{
for (size_t i = 0; i < fill.gradient->colors.size(); ++i)
{
fill.gradient->colors[i].color_ref = props.draw_fill_color_->get_hex_value();
}
}
}
if (props.draw_fill_image_name_)
{
const std::wstring style_name = L"bitmap:" + *props.draw_fill_image_name_;
if (office_element_ptr style = styles.find_by_style_name(style_name))
{
if (draw_fill_image * fill_image = dynamic_cast<draw_fill_image *>(style.get()))
{
fill.bitmap = oox::oox_bitmap_fill::create();
fill.bitmap->bTile = true;
std::wstring href = fill_image->xlink_attlist_.href_.get_value_or(L"");
if ( href.empty() )
{
office_binary_data* binary_data = dynamic_cast<office_binary_data*>(fill_image->office_binary_data_.get());
if (binary_data)
{
fill.bitmap->xlink_href_ = binary_data->write_to(document->get_folder());
}
}
else
{
fill.bitmap->xlink_href_ = href;
}
}
}
}
if (style_image)
{
if (style_background_image * image = dynamic_cast<style_background_image*>(style_image.get()))
{
if ((image) && (image->xlink_attlist_))
{
fill.type = 2;
fill.bitmap = oox::oox_bitmap_fill::create();
fill.bitmap->xlink_href_ = image->xlink_attlist_->href_.get_value_or(L"");
if (image->style_repeat_)
{
switch(image->style_repeat_->get_type())
{
case style_repeat::Repeat :
fill.bitmap->bTile = true;
fill.bitmap->bStretch = false;
break;
case style_repeat::Stretch :
fill.bitmap->bStretch = true;
fill.bitmap->bTile = false; //?? для background точно выключать
break;
}
}
if (image->draw_opacity_)
{
fill.opacity = image->draw_opacity_->get_value();
}
}
}
}
if (fill.bitmap)
{
if (props.style_repeat_)
{
switch(props.style_repeat_->get_type())
{
case style_repeat::Repeat :
fill.bitmap->bTile = true;
fill.bitmap->bStretch = false;
break;
case style_repeat::Stretch :
fill.bitmap->bStretch = true;
fill.bitmap->bTile = false;
break;
}
}
else
{
if (props.draw_fill_image_width_ && props.draw_fill_image_height_)
{
if (props.draw_fill_image_width_->get_type() == odf_types::length_or_percent::Percent &&
props.draw_fill_image_height_->get_type() == odf_types::length_or_percent::Percent)
{
if (props.draw_fill_image_width_->get_percent().get_value() > 99.9 &&
props.draw_fill_image_height_->get_percent().get_value() > 99.9 &&
props.draw_fill_image_width_->get_percent().get_value() < 100.1 &&
props.draw_fill_image_height_->get_percent().get_value() < 100.1 )
{
fill.bitmap->bStretch = true;
fill.bitmap->bTile = false;
}
}
}
}
if ((props.draw_color_mode_) && (*props.draw_color_mode_ == L"greyscale"))
fill.bitmap->bGrayscale = true;
}
if (props.draw_fill_gradient_name_)
{
const std::wstring style_name = L"gradient:" + *props.draw_fill_gradient_name_;
if (office_element_ptr style = styles.find_by_style_name(style_name))
{
if (draw_gradient *gradient_style = dynamic_cast<draw_gradient *>(style.get()))
{
fill.type = 3;
if (!fill.gradient) fill.gradient = oox::oox_gradient_fill::create();
Compute_GradientFill(gradient_style, fill.gradient);
if (fill.opacity)
{
for (size_t i = 0; i < fill.gradient->colors.size(); i++)
{
if (!fill.gradient->colors[i].opacity)
fill.gradient->colors[i].opacity = fill.opacity;
}
}
}
}
}
if (props.draw_fill_hatch_name_)
{
const std::wstring style_name = L"hatch:" + *props.draw_fill_hatch_name_;
if (office_element_ptr style = styles.find_by_style_name(style_name))
{
if (draw_hatch * image_style = dynamic_cast<draw_hatch *>(style.get()))
{
fill.type = 4;
fill.hatch = oox::oox_hatch_fill::create();
Compute_HatchFill(image_style, fill.hatch);
}
}
if ((fill.hatch) && (props.draw_fill_color_))
{
// NOTE: Do not use draw:fill-color for hatch
// fill.hatch->color_back_ref = props.draw_fill_color_->get_hex_value();
fill.hatch->color_back_ref = L"FFFFFF";
}
}
if (props.draw_fill_)
{
fill.type = props.draw_fill_->get_type();
}
switch(fill.type)
{
case 1:
if (!fill.solid) fill.type = -1;
case 2:
if (!fill.bitmap)
{
if (fill.solid) fill.type = 1;
else fill.type = -1;
}
break;
case 3:
if (!fill.gradient)
{
fill.gradient = oox::oox_gradient_fill::create();
}
break;
case 4:
if (!fill.hatch)
{
fill.hatch = oox::oox_hatch_fill::create();
}
break;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const wchar_t * draw_a::ns = L"draw";
const wchar_t * draw_a::name = L"a";
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/// draw-a-attlist
void draw_a::add_child_element( xml::sax * Reader, const std::wstring & Ns, const std::wstring & Name)
{
CP_CREATE_ELEMENT(content_);
}
void draw_a::add_attributes( const xml::attributes_wc_ptr & Attributes )
{
xlink_attlist_.add_attributes(Attributes);
CP_APPLY_ATTR(L"office:name", office_name_, std::wstring(L""));
CP_APPLY_ATTR(L"office:target-frame-name", office_target_frame_name_);
CP_APPLY_ATTR(L"text:style-name", text_style_name_, std::wstring(L""));
CP_APPLY_ATTR(L"text:visited-style-name", text_visited_style_name_, std::wstring(L""));
}
void draw_a::xlsx_convert(oox::xlsx_conversion_context & Context)
{
Context.get_drawing_context().start_action(L"");
Context.get_drawing_context().set_link(xlink_attlist_.href_.get_value_or(L""));
Context.get_drawing_context().end_action();
for (size_t i = 0; i < content_.size(); i++)
{
content_[i]->xlsx_convert(Context);
}
}
void draw_a::pptx_convert(oox::pptx_conversion_context & Context)
{
Context.get_slide_context().start_action(L"");
Context.get_slide_context().set_link(xlink_attlist_.href_.get_value_or(L""));
Context.get_slide_context().end_action();
for (size_t i = 0; i < content_.size(); i++)
{
content_[i]->pptx_convert(Context);
}
}
void draw_a::docx_convert(oox::docx_conversion_context & Context)
{
std::wstring rId = Context.add_hyperlink(xlink_attlist_.href_.get_value_or(L""), L"");//гиперлинк с объекта, а не с текста ..
for (size_t i = 0; i < content_.size(); i++)
{
content_[i]->docx_convert(Context);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void parse_string_to_points(std::wstring str, std::vector<length> & Points)
{
std::vector<std::wstring> Points_s;
boost::algorithm::split(Points_s,str, boost::algorithm::is_any_of(L" ,"), boost::algorithm::token_compress_on);
for (size_t i = 0; i < Points_s.size(); i++)
{
Points.push_back(length::parse(Points_s[i]) );
}
}
void docx_convert_transforms(std::wstring transformStr,std::vector<odf_reader::_property> & additional)
{
std::vector<std::wstring> transforms;
boost::algorithm::split(transforms,transformStr, boost::algorithm::is_any_of(L")"), boost::algorithm::token_compress_on);
for (size_t i = 0; i < transforms.size(); i++)
{
//_CP_LOG << "[info] : transform = " << t << L"\n";
std::vector<std::wstring> transform;
boost::algorithm::split(transform, transforms[i], boost::algorithm::is_any_of(L"("), boost::algorithm::token_compress_on);
if (transform.size() > 1)//тока с аргументами
{
int res=0;
if ((res = transform[0].find(L"translate")) >= 0) //перемещение
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (Points.size()>0)
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = 0;
if (Points.size()>1) y_pt = Points[1].get_value_unit(length::pt); //ее может не быть
//Context.get_drawing_context().set_translate(x_pt,y_pt);
additional.push_back(_property(L"svg:translate_x", x_pt));
additional.push_back(_property(L"svg:translate_y", y_pt));
}
}
else if ((res = transform[0].find(L"scale"))>=0)//масштабирование
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (Points.size()>0)
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = x_pt;
if (Points.size()>1)y_pt = Points[1].get_value_unit(length::pt);//ее может не быть
//Context.get_drawing_context().set_scale(x_pt,y_pt);
additional.push_back(_property(L"svg:scale_x", x_pt));
additional.push_back(_property(L"svg:scale_y", y_pt));
}
}
else if ((res = transform[0].find(L"rotate"))>=0)//вращение
{
double angle = boost::lexical_cast<double>(transform[1]);
additional.push_back(_property(L"svg:rotate", angle));
}
}
}
}
void xlsx_convert_transforms(std::wstring transformStr, oox::xlsx_conversion_context & Context)
{
std::vector<std::wstring> transforms;
boost::algorithm::split(transforms,transformStr, boost::algorithm::is_any_of(L")"), boost::algorithm::token_compress_on);
for (size_t i = 0; i < transforms.size(); i++)
{
std::vector<std::wstring> transform;
boost::algorithm::split(transform, transforms[i], boost::algorithm::is_any_of(L"("), boost::algorithm::token_compress_on);
if (transform.size() > 1)//тока с аргументами
{
size_t res=0;
if ((res = transform[0].find(L"translate")) != std::wstring::npos)//перемещение
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (Points.size()>0)
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = 0;
if (Points.size()>1)y_pt = Points[1].get_value_unit(length::pt);//ее может не быть
Context.get_drawing_context().set_translate(x_pt,y_pt);
}
}
else if ((res = transform[0].find(L"scale")) != std::wstring::npos)//масштабирование
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (Points.size()>0)
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = x_pt;
if (Points.size()>1)y_pt = Points[1].get_value_unit(length::pt);//ее может не быть
Context.get_drawing_context().set_scale(x_pt,y_pt);
}
}
else if ((res = transform[0].find(L"rotate")) != std::wstring::npos)//вращение
{
Context.get_drawing_context().set_rotate(boost::lexical_cast<double>(transform[1]), true);
}
else if ((res = transform[0].find(L"skewX")) != std::wstring::npos)//сдвиг
{
double angle = boost::lexical_cast<double>(transform[1]);
Context.get_drawing_context().set_property(_property(L"svg:skewX", angle));
}
else if ((res = transform[0].find(L"skewY")) != std::wstring::npos)//сдвиг
{
double angle = boost::lexical_cast<double>(transform[1]);
Context.get_drawing_context().set_property(_property(L"svg:skewY", angle));
}
}
}
}
void pptx_convert_transforms(std::wstring transformStr, oox::pptx_conversion_context & Context)
{
std::vector<std::wstring> transforms;
boost::algorithm::split(transforms,transformStr, boost::algorithm::is_any_of(L")"), boost::algorithm::token_compress_on);
for (size_t i = 0; i < transforms.size(); i++)
{
//_CP_LOG << "[info] : transform = " << t << L"\n";
std::vector<std::wstring> transform;
boost::algorithm::split(transform, transforms[i], boost::algorithm::is_any_of(L"("), boost::algorithm::token_compress_on);
if (transform.size() > 1)//тока с аргументами
{
size_t res = 0;
if ((res = transform[0].find(L"translate")) != std::wstring::npos)//перемещение
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (false == Points.empty())
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = 0;
if (Points.size()>1)y_pt = Points[1].get_value_unit(length::pt);//ее может не быть
Context.get_slide_context().set_translate(x_pt, y_pt);
}
}
else if ((res = transform[0].find(L"scale")) != std::wstring::npos)//масштабирование
{
std::vector<length> Points ;
parse_string_to_points(transform[1], Points);
if (false == Points.empty())
{
double x_pt = Points[0].get_value_unit(length::pt);
double y_pt = x_pt;
if (Points.size()>1)y_pt = Points[1].get_value_unit(length::pt);//ее может не быть
Context.get_slide_context().set_scale(x_pt, y_pt);
}
}
else if ((res = transform[0].find(L"rotate")) != std::wstring::npos)//вращение
{
Context.get_slide_context().set_rotate( boost::lexical_cast<double>(transform[1]), true);
}
else if ((res = transform[0].find(L"skewX")) != std::wstring::npos)//вращение
{
double angle = boost::lexical_cast<double>(transform[1]);
Context.get_slide_context().set_property(_property(L"svg:skewX", angle));
}
else if ((res = transform[0].find(L"skewY")) != std::wstring::npos)//вращение
{
double angle = boost::lexical_cast<double>(transform[1]);
Context.get_slide_context().set_property(_property(L"svg:skewY", angle));
}
}
}
}
}
}