33#include <osl/diagnose.h>
34#include <com/sun/star/i18n/CharacterClassification.hpp>
35#include <com/sun/star/i18n/DirectionProperty.hpp>
60 mxCharClass = CharacterClassification::create(xContext);
70 const char* pType =
dynamic_cast<DrawElement*
>(elem.
Children.front().get()) ?
"draw:a" :
"text:a";
73 aProps[
"xlink:type" ] =
"simple";
74 aProps[
"xlink:href" ] = elem.
URI;
75 aProps[
"office:target-frame-name" ] =
"_blank";
76 aProps[
"xlink:show" ] =
"new";
79 auto this_it = elem.
Children.begin();
80 while( this_it != elem.
Children.end() && this_it->get() != &elem )
82 (*this_it)->visitedBy( *
this, this_it );
90 if( elem.
Text.isEmpty() )
100 aProps[ OUString(
"text:style-name" ) ] =
104 OUString str(elem.
Text.toString());
111 for(
int i=1;
i< elem.
Text.getLength();
i++)
113 i18n::DirectionProperty
nType =
static_cast<i18n::DirectionProperty
>(xCC->getCharacterDirection( str,
i ));
114 if (
nType == i18n::DirectionProperty_RIGHT_TO_LEFT ||
115 nType == i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC ||
116 nType == i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING ||
117 nType == i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
128 str = ::comphelper::string::reverseCodePoints(str);
134 for (
int i = 0;
i < elem.
Text.getLength();
i++)
137 if (strToken == strSpace || strToken == strNbSpace)
139 aProps[
"text:c"] =
"1";
143 else if (strToken == tabSpace)
152 auto this_it = elem.
Children.begin();
153 while( this_it != elem.
Children.end() && this_it->get() != &elem )
155 (*this_it)->visitedBy( *
this, this_it );
169 const char* pTagType =
"text:p";
174 auto this_it = elem.
Children.begin();
175 while( this_it != elem.
Children.end() && this_it->get() != &elem )
177 (*this_it)->visitedBy( *
this, this_it );
188 double rel_x = rElem.
x, rel_y = rElem.
y;
194 while ((pAnchor = pAnchor->
Parent))
206 ? std::u16string_view(
u"character") : std::u16string_view(
u"paragraph");
211 rProps[
"text:anchor-type" ] =
"page";
212 rProps[
"text:anchor-page-number" ] = OUString::number(pPage->
PageNumber);
218 rProps[
"draw:z-index" ] = OUString::number( rElem.
ZOrder );
236 double fRotate, fShearX;
240 OUStringBuffer
aBuf( 256 );
250 rel_y -= std::abs(rElem.
h);
253 aBuf.append(
"scale( 1.0 -1.0 )");
257 aBuf.append(
"skewX( " );
258 aBuf.append( fShearX );
263 if( !
aBuf.isEmpty() )
265 aBuf.append(
"rotate( " );
266 aBuf.append( -fRotate );
272 if( !
aBuf.isEmpty() )
274 aBuf.append(
"translate( " );
281 rProps[
"draw:transform" ] =
aBuf.makeStringAndClear();
297 auto this_it = elem.
Children.begin();
298 while( this_it != elem.
Children.end() && this_it->get() != &elem )
300 (*this_it)->visitedBy( *
this, this_it );
323 for ( sal_uInt32 j = 0; j< b2dPolygon.
count(); j++ )
361 OUStringBuffer
aBuf( 64 );
362 aBuf.append(
"0 0 " );
366 aProps[
"svg:viewBox" ] =
aBuf.makeStringAndClear();
388 auto this_it = elem.
Children.begin();
389 while( this_it != elem.
Children.end() && this_it->get() != &elem )
391 (*this_it)->visitedBy( *
this, this_it );
401 for(
const auto& rxChild : elem.
Children )
408 for(
auto child_it = pPage->
Children.begin(); child_it != pPage->
Children.end(); ++child_it )
410 if(
dynamic_cast<DrawElement*
>(child_it->get()) != nullptr )
411 (*child_it)->
visitedBy( *
this, child_it );
421 if(
dynamic_cast<DrawElement*
>(it->get()) != nullptr )
422 (*it)->visitedBy( *
this, it );
458 auto next_it = elemIt;
505 auto prev = rParentIt;
524 if( pPrevPara->
y + pPrevPara->
h + 2*head_line_height > elem.
y )
537 if( pPrevText && pThisText )
577 std::list< std::unique_ptr<Element> >::iterator page_element, next_page_element;
578 next_page_element = elem.
Children.begin();
579 double fCurLineHeight = 0.0;
580 int nCurLineElements = 0;
581 double line_left = elem.
w, line_right = 0.0;
582 double column_width = elem.
w*0.75;
584 while( next_page_element != elem.
Children.end() )
586 page_element = next_page_element++;
590 pCurPara = pPagePara;
592 fCurLineHeight = 0.0;
593 nCurLineElements = 0;
594 for(
const auto& rxChild : pCurPara->
Children )
599 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pTestText->
h)/
double(nCurLineElements+1);
608 if( ! pDraw &&
pLink && !
pLink->Children.empty() )
614 bool bInsertToParagraph =
false;
616 if( pCurPara && pDraw->
y < pCurPara->
y + pCurPara->
h )
618 if( pDraw->
h < fCurLineHeight * 1.5 )
620 bInsertToParagraph =
true;
621 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pDraw->
h)/
double(nCurLineElements+1);
628 else if( next_page_element != elem.
Children.end() )
634 if( pPara && ! pPara->
Children.empty() )
635 pText = pPara->
Children.front()->dynCastAsTextElement();
638 pDraw->
h < pText->
h*1.5 &&
640 ( ( pDraw->
y >= pText->
y && pDraw->
y <= pText->
y+pText->
h ) ||
641 ( pDraw->
y+pDraw->
h >= pText->
y && pDraw->
y+pDraw->
h <= pText->
y+pText->
h )
645 bInsertToParagraph =
true;
646 fCurLineHeight = pDraw->
h;
647 nCurLineElements = 1;
648 line_left = pDraw->
x;
649 line_right = pDraw->
x + pDraw->
w;
657 if( ! bInsertToParagraph )
665 if( ! pText &&
pLink && !
pLink->Children.empty() )
666 pText =
pLink->Children.front()->dynCastAsTextElement();
674 if( nCurLineElements > 0 )
678 if( pGeo->
y > pCurPara->
y+pCurPara->
h + fCurLineHeight*0.5 )
680 else if( pGeo->
y > (pCurPara->
y+pCurPara->
h - fCurLineHeight*0.05) )
684 if( (line_right - line_left) < pCurPara->
w*0.75 )
687 else if( (line_right - line_left) < column_width*0.75 )
695 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pGeo->
h)/
double(nCurLineElements+1);
697 if( pGeo->
x < line_left )
699 if( pGeo->
x+pGeo->
w > line_right )
700 line_right = pGeo->
x+pGeo->
w;
704 fCurLineHeight = pGeo->
h;
705 nCurLineElements = 1;
707 line_right = pGeo->
x + pGeo->
w;
718 page_element = elem.
Children.insert( page_element, std::unique_ptr<Element>(pCurPara) );
722 next_page_element = page_element;
723 ++ next_page_element;
725 Element* pCurEle = page_element->get();
727 OSL_ENSURE( !pText || pCurEle == pText || pCurEle ==
pLink,
"paragraph child list in disorder" );
750 auto isParagraphElement = [](std::unique_ptr<Element>& rxChild) ->
bool {
757 auto it = std::find_if(rElem.
Children.begin(), rElem.
Children.end(), isParagraphElement);
765 while( ++next_it != rElem.
Children.end() && pNextPara ==
nullptr )
769 if( pNextPara && pNextPara->
y > rPara.
y+rPara.
h*2 )
779 auto rit = std::find_if(rElem.
Children.rbegin(), rElem.
Children.rend(), isParagraphElement);
787 std::list< std::unique_ptr<Element> >::reverse_iterator next_it = rit;
789 while( ++next_it != rElem.
Children.rend() && pNextPara ==
nullptr )
793 if( pNextPara && pNextPara->
y < rPara.
y-rPara.
h*2 )
805 OSL_FAIL(
"empty paragraph optimized" );
810 auto next = rParent.
Children.begin();
813 bool bRotatedFrame =
false;
818 bRotatedFrame =
true;
820 while( next != rParent.
Children.end() )
822 bool bConcat =
false;
828 bool bPara = strspn(
"ParagraphElement",
typeid(rParent).
name());
842 && ! pNext->
Text.isEmpty()
843 && pNext->
Text[0] !=
' '
844 && ! pCur->
Text.isEmpty()
845 && pCur->
Text[pCur->
Text.getLength() - 1] !=
' '
849 if( pNext->
y > pCur->
y+pCur->
h )
855 || aLastCode == 0x2010
856 || (aLastCode >= 0x2012 && aLastCode <= 0x2015)
857 || aLastCode == 0xff0d
861 pCur->
Text.setLength( pCur->
Text.getLength()-1 );
864 else if( aLastCode != 0x2011 )
866 pCur->
Text.append(
' ' );
873 if( pCur->
x + pCur->
w + pNext->
h*0.15 < pNext->
x )
875 pCur->
Text.append(
' ' );
889 if (pPara && pPara->
bRtl)
894 bool bNeedReverse=
false;
895 str = pNext->
Text.toString();
896 for (sal_Int32
i=0;
i < str.getLength();
i++)
901 pCur->
Text.append(OUStringChar(str[
i]));
905 tempStr = ::comphelper::string::reverseCodePoints(tempStr);
906 pCur->
Text.append(tempStr);
909 bNeedReverse =
false;
913 tempStr += OUStringChar(str[
i]);
920 tempStr = ::comphelper::string::reverseCodePoints(tempStr);
921 pCur->
Text.append(tempStr);
925 pCur->
Text.append(tempStr);
971 aProps[
"style:family" ] =
"graphic";
979 aGCProps[
"draw:stroke" ] =
"solid";
987 aGCProps[
"draw:stroke" ] =
"dash";
988 aGCProps[
"draw:stroke-dash" ] =
1000 aGCProps[
"draw:stroke" ] =
"none";
1006 aGCProps[
"draw:fill" ] =
"solid";
1011 aGCProps[
"draw:fill" ] =
"none";
1016 aStyle.
SubStyles.push_back( &aSubStyle );
1029 aProps[
"style:family" ] =
"text";
1036 aFontProps[
"fo:font-family" ] = rFont.
familyName;
1037 aFontProps[
"style:font-family-asian" ] = rFont.
familyName;
1038 aFontProps[
"style:font-family-complex" ] = rFont.
familyName;
1041 aFontProps[
"fo:font-weight" ] = rFont.
fontWeight;
1042 aFontProps[
"style:font-weight-asian" ] = rFont.
fontWeight;
1043 aFontProps[
"style:font-weight-complex" ] = rFont.
fontWeight;
1048 aFontProps[
"fo:font-style" ] =
"italic";
1049 aFontProps[
"style:font-style-asian" ] =
"italic";
1050 aFontProps[
"style:font-style-complex" ] =
"italic";
1056 aFontProps[
"style:text-underline-style" ] =
"solid";
1057 aFontProps[
"style:text-underline-width" ] =
"auto";
1058 aFontProps[
"style:text-underline-color" ] =
"font-color";
1063 aFontProps[
"style:text-outline" ] =
"true";
1067 aFontProps[
"fo:font-size" ] = aFSize;
1068 aFontProps[
"style:font-size-asian" ] = aFSize;
1069 aFontProps[
"style:font-size-complex" ] = aFSize;
1077 aStyle.
SubStyles.push_back( &aSubStyle );
1098 bool bIsCenter =
false;
1099 if( elem.
w < ( p_w/2) )
1101 double delta = elem.
w/4;
1104 if( elem.
w < p_w/8 )
1106 if( fabs( elem.
x+elem.
w/2 - ( p_x+ p_w/2) ) < delta ||
1107 (pPage && fabs( elem.
x+elem.
w/2 - (pPage->
x + pPage->
w/2) ) < delta) )
1110 aParaProps[
"fo:text-align" ] =
"center";
1113 if( ! bIsCenter && elem.
x > p_x + p_w/10 )
1116 OUStringBuffer
aBuf( 32 );
1118 aBuf.append(
"mm" );
1119 aParaProps[
"fo:margin-left" ] =
aBuf.makeStringAndClear();
1124 auto it = rParentIt;
1132 OUStringBuffer
aBuf( 32 );
1134 aBuf.append(
"mm" );
1135 aParaProps[
"fo:margin-bottom" ] =
aBuf.makeStringAndClear();
1140 if( ! aParaProps.empty() )
1143 aProps[
"style:family" ] =
"paragraph";
1146 aStyle.
SubStyles.push_back( &aSubStyle );
1156 aProps[
"style:family" ] =
"graphic";
1160 aGCProps[
"draw:stroke" ] =
"none";
1161 aGCProps[
"draw:fill" ] =
"none";
1162 aGCProps[
"draw:auto-grow-height" ] =
"true";
1163 aGCProps[
"draw:auto-grow-width" ] =
"true";
1164 aGCProps[
"draw:textarea-horizontal-align" ] =
"left";
1165 aGCProps[
"draw:textarea-vertical-align" ] =
"top";
1166 aGCProps[
"fo:min-height"] =
"0cm";
1167 aGCProps[
"fo:min-width"] =
"0cm";
1168 aGCProps[
"fo:padding-top" ] =
"0cm";
1169 aGCProps[
"fo:padding-left" ] =
"0cm";
1170 aGCProps[
"fo:padding-right" ] =
"0cm";
1171 aGCProps[
"fo:padding-bottom" ] =
"0cm";
1175 aStyle.
SubStyles.push_back( &aSubStyle );
1187 const OUString& rMasterPageName )
1197 aProps[
"style:family" ] =
"paragraph";
1198 aProps[
"style:master-page-name" ] = rMasterPageName;
1224 for(
const auto& rxChild : elem.
Children )
1232 if( rxChild->x + rxChild->w > elem.
w - elem.
RightMargin )
1260 left_margin = rtl_math_round( left_margin, 0, rtl_math_RoundingMode_Floor );
1261 top_margin = rtl_math_round( top_margin, 0, rtl_math_RoundingMode_Floor );
1263 right_margin = rtl_math_round( right_margin, right_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1264 bottom_margin = rtl_math_round( bottom_margin, bottom_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1268 if( left_margin > page_width/2.0 - 10 )
1270 if( right_margin > page_width/2.0 - 10 )
1272 if( top_margin > page_height/2.0 - 10 )
1274 if( bottom_margin > page_height/2.0 - 10 )
1278 if( left_margin < 0 )
1280 if( right_margin < 0 )
1282 if( top_margin < 0 )
1284 if( bottom_margin < 0 )
1288 if( right_margin > left_margin*1.5 )
1289 right_margin = left_margin;
1299 aPageLayoutProps[
"fo:page-width" ] =
unitMMString( page_width );
1300 aPageLayoutProps[
"fo:page-height" ] =
unitMMString( page_height );
1301 aPageLayoutProps[
"style:print-orientation" ]
1302 = elem.
w < elem.
h ? std::u16string_view(
u"portrait") : std::u16string_view(
u"landscape");
1303 aPageLayoutProps[
"fo:margin-top" ] =
unitMMString( top_margin );
1304 aPageLayoutProps[
"fo:margin-bottom" ] =
unitMMString( bottom_margin );
1305 aPageLayoutProps[
"fo:margin-left" ] =
unitMMString( left_margin );
1306 aPageLayoutProps[
"fo:margin-right" ] =
unitMMString( right_margin );
1307 aPageLayoutProps[
"style:writing-mode" ]=
"lr-tb";
1316 aPageProps[
"style:page-layout-name" ] = aMasterPageLayoutName;
1322 elem.
HeaderElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1324 aMPStyle.
SubStyles.push_back( &aHeaderStyle );
1328 elem.
FooterElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1330 aMPStyle.
SubStyles.push_back( &aFooterStyle );
1344 pFirstPara->
Parent = &elem;
1345 elem.
Children.push_front( std::unique_ptr<Element>(pFirstPara) );
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
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
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)
sal_Int32 setProperties(sal_Int32 nStyleId, PropertyMap &&rNewProps)
OUString getStyleName(sal_Int32 nStyle) const
sal_Int32 impl_getStyleId(const Style &rStyle, bool bSubStyle)
const PropertyMap * getProperties(sal_Int32 nStyleId) const
sal_Int32 getStyleId(const Style &rStyle)
static void fillFrameProps(DrawElement &rElem, PropertyMap &rProps, const EmitContext &rEmitContext)
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
const css::uno::Reference< css::i18n::XCharacterClassification > & GetCharacterClassification()
EmitContext & m_rEmitContext
css::uno::Reference< css::i18n::XCharacterClassification > mxCharClass
PDFIProcessor & m_rProcessor
static void setFirstOnPage(ParagraphElement &rElem, StyleContainer &rStyles, const OUString &rMasterPageName)
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
StyleContainer & m_rStyleContainer
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
void checkHeaderAndFooter(PageElement &rElem)
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIter
PDFIProcessor & m_rProcessor
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)
double convPx2mm(double fPix)
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
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
bool isRotatedOrSkewed() const
basegfx::B2DHomMatrix Transformation
OUString GetLineCapString() const
OUString GetLineJoinString() const
std::vector< double > DashArray
basegfx::B2DPolyPolygon Clip
std::unique_ptr< Element > FooterElement
std::unique_ptr< Element > HeaderElement
virtual void visitedBy(ElementTreeVisitor &, const std::list< std::unique_ptr< Element > >::const_iterator &rParentIt) override
To be implemented by every tree node that needs to be visitable.
void resolveFontStyles(PDFIProcessor const &rProc)
TextElement * getFirstTextChild() const
double getLineHeight(PDFIProcessor &rProc) const
bool isSingleLined(PDFIProcessor const &rProc) const
basegfx::B2DPolyPolygon PolyPoly
std::vector< Style * > SubStyles
Element * ContainedElement
virtual const TextElement * dynCastAsTextElement() const override
To avoid some dynamic_cast cost.