29#include <osl/diagnose.h>
30#include <rtl/math.hxx>
31#include <com/sun/star/i18n/BreakIterator.hpp>
32#include <com/sun/star/i18n/CharacterClassification.hpp>
33#include <com/sun/star/i18n/ScriptType.hpp>
34#include <com/sun/star/i18n/DirectionProperty.hpp>
63 mxCharClass = CharacterClassification::create(xContext);
73 const char* pType =
dynamic_cast<DrawElement*
>(elem.
Children.front().get()) ?
"draw:a" :
"text:a";
76 aProps[
"xlink:type" ] =
"simple";
77 aProps[
"xlink:href" ] = elem.
URI;
78 aProps[
"office:target-frame-name" ] =
"_blank";
79 aProps[
"xlink:show" ] =
"new";
82 auto this_it = elem.
Children.begin();
83 while( this_it != elem.
Children.end() && this_it->get() != &elem )
85 (*this_it)->visitedBy( *
this, this_it );
93 if( elem.
Text.isEmpty() )
96 OUString strSpace(
u' ');
97 OUString strNbSpace(
u'\x00A0');
98 OUString tabSpace(
u'\x0009');
102 aProps[ OUString(
"text:style-name" ) ] =
106 OUString str(elem.
Text.toString());
113 for(
int i=1;
i< elem.
Text.getLength();
i++)
115 css::i18n::DirectionProperty
nType =
static_cast<css::i18n::DirectionProperty
>(xCC->getCharacterDirection( str,
i ));
116 if (
nType == css::i18n::DirectionProperty_RIGHT_TO_LEFT ||
117 nType == css::i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC ||
118 nType == css::i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING ||
119 nType == css::i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
130 str = ::comphelper::string::reverseCodePoints(str);
136 for(
int i=0;
i< elem.
Text.getLength();
i++)
138 OUString strToken= str.copy(
i,1) ;
139 if( strSpace == strToken || strNbSpace == strToken )
141 aProps[
"text:c" ] =
"1";
147 if( tabSpace == strToken )
159 auto this_it = elem.
Children.begin();
160 while( this_it != elem.
Children.end() && this_it->get() != &elem )
162 (*this_it)->visitedBy( *
this, this_it );
176 const char* pTagType =
"text:p";
181 auto this_it = elem.
Children.begin();
182 while( this_it != elem.
Children.end() && this_it->get() != &elem )
184 (*this_it)->visitedBy( *
this, this_it );
197 static constexpr OUStringLiteral sDrawZIndex =
u"draw:z-index";
198 static constexpr OUStringLiteral sDrawStyleName =
u"draw:style-name";
199 static constexpr OUStringLiteral sDrawTextStyleName =
u"draw:text-style-name";
200 static constexpr OUStringLiteral sSvgX =
u"svg:x";
201 static constexpr OUStringLiteral sSvgY =
u"svg:y";
202 static constexpr OUStringLiteral sSvgWidth =
u"svg:width";
203 static constexpr OUStringLiteral sSvgHeight =
u"svg:height";
204 static constexpr OUStringLiteral sDrawTransform =
u"draw:transform";
206 rProps[ sDrawZIndex ] = OUString::number( rElem.
ZOrder );
224 OUStringBuffer
aBuf(256);
240 aBuf.append(
"matrix(");
254 rProps[ sDrawTransform ] =
aBuf.makeStringAndClear();
270 auto this_it = elem.
Children.begin();
271 while( this_it != elem.
Children.end() && this_it->get() != &elem )
273 (*this_it)->visitedBy( *
this, this_it );
296 for ( sal_uInt32 j = 0; j< b2dPolygon.
count(); j++ )
337 OUStringBuffer
aBuf( 64 );
338 aBuf.append(
"0 0 " );
342 aProps[
"svg:viewBox" ] =
aBuf.makeStringAndClear();
369 auto this_it = elem.
Children.begin();
370 while( this_it != elem.
Children.end() && this_it->get() != &elem )
372 (*this_it)->visitedBy( *
this, this_it );
385 auto this_it = elem.
Children.begin();
386 while( this_it != elem.
Children.end() && this_it->get() != &elem )
388 (*this_it)->visitedBy( *
this, this_it );
426 auto next_it = elemIt;
491 std::list< std::unique_ptr<Element> >::iterator page_element, next_page_element;
492 next_page_element = elem.
Children.begin();
493 double fCurLineHeight = 0.0;
494 int nCurLineElements = 0;
495 double line_left = elem.
w, line_right = 0.0;
496 double column_width = elem.
w*0.75;
498 while( next_page_element != elem.
Children.end() )
500 page_element = next_page_element++;
504 pCurPara = pPagePara;
506 fCurLineHeight = 0.0;
507 nCurLineElements = 0;
508 for(
const auto& rxChild : pCurPara->
Children )
513 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pTestText->
h)/
double(nCurLineElements+1);
522 if( ! pDraw &&
pLink && !
pLink->Children.empty() )
528 bool bInsertToParagraph =
false;
530 if( pCurPara && pDraw->
y < pCurPara->
y + pCurPara->
h )
532 if( pDraw->
h < fCurLineHeight * 1.5 )
534 bInsertToParagraph =
true;
535 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pDraw->
h)/
double(nCurLineElements+1);
542 else if( next_page_element != elem.
Children.end() )
548 if( pPara && ! pPara->
Children.empty() )
549 pText = pPara->
Children.front()->dynCastAsTextElement();
552 pDraw->
h < pText->
h*1.5 &&
554 ( ( pDraw->
y >= pText->
y && pDraw->
y <= pText->
y+pText->
h ) ||
555 ( pDraw->
y+pDraw->
h >= pText->
y && pDraw->
y+pDraw->
h <= pText->
y+pText->
h )
559 bInsertToParagraph =
true;
560 fCurLineHeight = pDraw->
h;
561 nCurLineElements = 1;
562 line_left = pDraw->
x;
563 line_right = pDraw->
x + pDraw->
w;
571 if( ! bInsertToParagraph )
579 if( ! pText &&
pLink && !
pLink->Children.empty() )
580 pText =
pLink->Children.front()->dynCastAsTextElement();
588 if( nCurLineElements > 0 )
592 if( pGeo->
y > pCurPara->
y + pCurPara->
h + fCurLineHeight*0.5 )
594 else if( pGeo->
y > (pCurPara->
y+pCurPara->
h - fCurLineHeight*0.05) )
598 if( (line_right - line_left) < pCurPara->
w*0.75 )
601 else if( (line_right - line_left) < column_width*0.75 )
613 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pGeo->
h)/
double(nCurLineElements+1);
615 if( pGeo->
x < line_left )
617 if( pGeo->
x+pGeo->
w > line_right )
618 line_right = pGeo->
x+pGeo->
w;
622 fCurLineHeight = pGeo->
h;
623 nCurLineElements = 1;
625 line_right = pGeo->
x + pGeo->
w;
637 page_element = elem.
Children.insert( page_element, std::unique_ptr<Element>(pCurPara) );
641 next_page_element = page_element;
642 ++ next_page_element;
644 Element* pCurEle = page_element->get();
646 OSL_ENSURE( !pText || pCurEle == pText || pCurEle ==
pLink,
"paragraph child list in disorder" );
657 for (sal_Int32
i = 0;
i != pTextElem->
Text.getLength(); ++
i) {
658 if (pTextElem->
Text[
i] !=
' ') {
669 OSL_FAIL(
"empty paragraph optimized" );
674 auto next = rParent.
Children.begin();
677 while( next != rParent.
Children.end() )
679 bool bConcat =
false;
686 bool bPara = strspn(
"ParagraphElement",
typeid(rParent).
name());
707 if (pPara && pPara->
bRtl)
712 bool bNeedReverse=
false;
713 str = pNext->
Text.toString();
714 for (sal_Int32
i=0;
i < str.getLength();
i++)
719 pCur->
Text.append(OUStringChar(str[
i]));
723 tempStr = ::comphelper::string::reverseCodePoints(tempStr);
724 pCur->
Text.append(tempStr);
727 bNeedReverse =
false;
731 tempStr += OUStringChar(str[
i]);
738 tempStr = ::comphelper::string::reverseCodePoints(tempStr);
739 pCur->
Text.append(tempStr);
743 pCur->
Text.append(tempStr);
786 aProps[
"style:family" ] =
"graphic";
787 aProps[
"style:parent-style-name" ] =
"standard";
797 aGCProps[
"draw:stroke" ] =
"solid";
805 aGCProps[
"draw:stroke" ] =
"dash";
806 aGCProps[
"draw:stroke-dash" ] =
820 aGCProps[
"draw:stroke" ] =
"none";
826 aGCProps[
"draw:fill" ] =
"solid";
833 aGCProps[
"draw:fill" ] =
"none";
838 aStyle.
SubStyles.push_back( &aSubStyle );
850 props[
"fo:font-size"] = aFSize;
851 props[
"style:font-size-asian"] = aFSize;
852 props[
"style:font-size-complex"] = aFSize;
859 aProps[
"style:family" ] =
"text";
866 aFontProps[
"fo:font-family" ] = rFont.
familyName;
867 aFontProps[
"style:font-family-asian" ] = rFont.
familyName;
868 aFontProps[
"style:font-family-complex" ] = rFont.
familyName;
871 aFontProps[
"fo:font-weight" ] = rFont.
fontWeight;
872 aFontProps[
"style:font-weight-asian" ] = rFont.
fontWeight;
873 aFontProps[
"style:font-weight-complex" ] = rFont.
fontWeight;
878 aFontProps[
"fo:font-style" ] =
"italic";
879 aFontProps[
"style:font-style-asian" ] =
"italic";
880 aFontProps[
"style:font-style-complex" ] =
"italic";
886 aFontProps[
"style:text-underline-style" ] =
"solid";
887 aFontProps[
"style:text-underline-width" ] =
"auto";
888 aFontProps[
"style:text-underline-color" ] =
"font-color";
893 aFontProps[
"style:text-outline" ] =
"true";
903 double fRotate, fShearX;
906 double textScale = 100 * aScale.
getX() / aScale.
getY();
907 if (((textScale >= 1) && (textScale <= 99)) ||
908 ((textScale >= 101) && (textScale <= 999)))
915 aStyle.
SubStyles.push_back( &aSubStyle );
923 aProps[
"style:family" ] =
"paragraph";
929 aParProps[
"fo:text-align"] =
"start";
931 aParProps[
"style:writing-mode"] =
"rl-tb";
933 aParProps[
"style:writing-mode"] =
"lr-tb";
937 aStyle.
SubStyles.push_back( &aSubStyle );
947 props1[
"style:family" ] =
"graphic";
948 props1[
"style:parent-style-name" ] =
"standard";
954 aGCProps[
"draw:stroke" ] =
"none";
955 aGCProps[
"draw:fill" ] =
"none";
956 aGCProps[
"draw:auto-grow-height" ] =
"true";
957 aGCProps[
"draw:auto-grow-width" ] =
"true";
958 aGCProps[
"draw:textarea-horizontal-align" ] =
"left";
959 aGCProps[
"draw:textarea-vertical-align" ] =
"top";
960 aGCProps[
"fo:min-height"] =
"0cm";
961 aGCProps[
"fo:min-width"] =
"0cm";
962 aGCProps[
"fo:padding-top" ] =
"0cm";
963 aGCProps[
"fo:padding-left" ] =
"0cm";
964 aGCProps[
"fo:padding-right" ] =
"0cm";
965 aGCProps[
"fo:padding-bottom" ] =
"0cm";
976 props2[
"style:family"] =
"paragraph";
1008 for(
const auto& rxChild : elem.
Children )
1027 left_margin = rtl_math_round( left_margin, 0, rtl_math_RoundingMode_Floor );
1028 top_margin = rtl_math_round( top_margin, 0, rtl_math_RoundingMode_Floor );
1030 right_margin = rtl_math_round( right_margin, right_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1031 bottom_margin = rtl_math_round( bottom_margin, bottom_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1035 if( left_margin > page_width/2.0 - 10 )
1037 if( right_margin > page_width/2.0 - 10 )
1039 if( top_margin > page_height/2.0 - 10 )
1041 if( bottom_margin > page_height/2.0 - 10 )
1045 if( left_margin < 0 )
1047 if( right_margin < 0 )
1049 if( top_margin < 0 )
1051 if( bottom_margin < 0 )
1055 if( right_margin > left_margin*1.5 )
1056 right_margin = left_margin;
1066 aPageLayoutProps[
"fo:margin-top" ] =
unitMMString( top_margin );
1067 aPageLayoutProps[
"fo:margin-bottom" ] =
unitMMString( bottom_margin );
1068 aPageLayoutProps[
"fo:margin-left" ] =
unitMMString( left_margin );
1069 aPageLayoutProps[
"fo:margin-right" ] =
unitMMString( right_margin );
1070 aPageLayoutProps[
"fo:page-width" ] =
unitMMString( page_width );
1071 aPageLayoutProps[
"fo:page-height" ] =
unitMMString( page_height );
1072 aPageLayoutProps[
"style:print-orientation" ]= elem.
w < elem.
h ? std::u16string_view(
u"portrait") : std::u16string_view(
u"landscape");
1073 aPageLayoutProps[
"style:writing-mode" ]=
"lr-tb";
1082 aPageProps[
"style:page-layout-name" ] = aMasterPageLayoutName;
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
void translate(double fX, double fY)
double get(sal_uInt16 nRow, sal_uInt16 nColumn) const
void scale(double fX, double fY)
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
void setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon &rPolygon)
bool isPrevControlPointUsed(sal_uInt32 nIndex) const
void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
bool isNextControlPointUsed(sal_uInt32 nIndex) const
void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const
void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const
basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const
css::uno::Reference< css::i18n::XCharacterClassification > mxCharClass
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
const bool m_bWriteDrawDocument
writes Impress doc when false
const css::uno::Reference< css::i18n::XCharacterClassification > & GetCharacterClassification()
EmitContext & m_rEmitContext
static void fillFrameProps(DrawElement &rElem, PropertyMap &rProps, const EmitContext &rEmitContext, bool bWasTransformed)
StyleContainer & m_rStyleContainer
PDFIProcessor & m_rProcessor
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
void optimizeTextElements(Element &rParent)
const css::uno::Reference< css::i18n::XBreakIterator > & GetBreakIterator()
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
PDFIProcessor & m_rProcessor
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIter
static ParagraphElement * createParagraphElement(Element *pParent)
void writeBase64EncodedStream(ImageId nImageId, EmitContext &rContext)
css::uno::Reference< css::uno::XComponentContext > m_xContext
const GraphicsContext & getGraphicsContext(sal_Int32 nGCId) const
const FontAttributes & getFont(sal_Int32 nFontId) const
const css::uno::Reference< css::task::XStatusIndicator > & getStatusIndicator() const
static void sortElements(Element *pElement)
static OUString SubstituteBidiMirrored(const OUString &rString)
sal_Int32 getGCId(const GraphicsContext &rGC)
OUString getStyleName(sal_Int32 nStyle) const
sal_Int32 impl_getStyleId(const Style &rStyle, bool bSubStyle)
sal_Int32 getStandardStyleId(std::string_view rFamily)
sal_Int32 getStyleId(const Style &rStyle)
virtual void write(const OUString &rString)=0
Write PCTEXT as-is to output.
virtual void endTag(const char *pTag)=0
Close previously opened tag.
virtual void beginTag(const char *pTag, const PropertyMap &rProperties)=0
Open up a tag with the given properties.
#define SAL_INFO(area, stream)
OUString exportToSvgD(const B2DPolyPolygon &rPolyPoly, bool bUseRelativeCoordinates, bool bDetectQuadraticBeziers, bool bHandleRelativeNextPointCompatible, bool bOOXMLMotionPath=false)
OUString convertPixelToUnitString(double fPix)
OUString getColorString(const css::rendering::ARGBColor &)
Convert color to "#FEFEFE" color notation.
double convmm2Px(double fMM)
static bool isSpaces(TextElement *pTextElem)
double convPx2mm(double fPix)
OUString getPercentString(double value)
double GetAverageTransformationScale(const basegfx::B2DHomMatrix &matrix)
OUString unitMMString(double fMM)
std::unordered_map< OUString, OUString > PropertyMap
double convPx2mmPrec2(double fPix)
round to 2 decimal places
static void SetFontsizeProperties(PropertyMap &props, double fontSize)
bool isComplex(const css::uno::Reference< css::i18n::XBreakIterator > &rBreakIterator, TextElement *const pTextElem)
void FillDashStyleProps(PropertyMap &props, const std::vector< double > &dashArray, double scale)
#define PDFI_OUTDEV_RESOLUTION
static void setParent(std::list< std::unique_ptr< Element > >::iterator const &el, Element *pNewParent)
el must be a valid dereferenceable iterator of el->Parent->Children pNewParent must not be NULL
std::list< std::unique_ptr< Element > > Children
void applyToChildren(ElementTreeVisitor &)
Apply visitor to all children.
void updateGeometryWith(const Element *pMergeFrom)
Union element geometry with given element.
css::uno::Reference< css::uno::XComponentContext > m_xContext
PDFIProcessor & rProcessor
css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator
css::rendering::ARGBColor FillColor
css::rendering::ARGBColor LineColor
basegfx::B2DHomMatrix Transformation
OUString GetLineCapString() const
OUString GetLineJoinString() const
std::vector< double > DashArray
basegfx::B2DPolyPolygon Clip
void resolveFontStyles(PDFIProcessor const &rProc)
basegfx::B2DPolyPolygon PolyPoly
std::vector< Style * > SubStyles
virtual const TextElement * dynCastAsTextElement() const override
To avoid some dynamic_cast cost.