22 #include <string_view>
33 #include <osl/diagnose.h>
45 const char* pType =
dynamic_cast<DrawElement*
>(elem.
Children.front().get()) ?
"draw:a" :
"text:a";
48 aProps[
"xlink:type" ] =
"simple";
49 aProps[
"xlink:href" ] = elem.
URI;
50 aProps[
"office:target-frame-name" ] =
"_blank";
51 aProps[
"xlink:show" ] =
"new";
54 auto this_it = elem.
Children.begin();
55 while( this_it != elem.
Children.end() && this_it->get() != &elem )
57 (*this_it)->visitedBy( *
this, this_it );
65 if( elem.
Text.isEmpty() )
71 aProps[ OUString(
"text:style-name" ) ] =
77 auto this_it = elem.
Children.begin();
78 while( this_it != elem.
Children.end() && this_it->get() != &elem )
80 (*this_it)->visitedBy( *
this, this_it );
94 const char* pTagType =
"text:p";
99 auto this_it = elem.
Children.begin();
100 while( this_it != elem.
Children.end() && this_it->get() != &elem )
102 (*this_it)->visitedBy( *
this, this_it );
113 double rel_x = rElem.
x, rel_y = rElem.
y;
119 while ((pAnchor = pAnchor->
Parent))
121 if ((pParaElt = dynamic_cast<ParagraphElement*>(pAnchor)))
123 if ((pPage = dynamic_cast<PageElement*>(pAnchor)))
131 ? std::u16string_view(
u"character") : std::u16string_view(
u"paragraph");
136 rProps[
"text:anchor-type" ] =
"page";
137 rProps[
"text:anchor-page-number" ] = OUString::number(pPage->
PageNumber);
143 rProps[
"draw:z-index" ] = OUString::number( rElem.
ZOrder );
161 double fRotate, fShearX;
165 OUStringBuffer
aBuf( 256 );
175 rel_y -= std::abs(rElem.
h);
178 aBuf.append(
"scale( 1.0 -1.0 )");
182 aBuf.append(
"skewX( " );
183 aBuf.append( fShearX );
188 if( !aBuf.isEmpty() )
190 aBuf.append(
"rotate( " );
191 aBuf.append( -fRotate );
197 if( !aBuf.isEmpty() )
199 aBuf.append(
"translate( " );
206 rProps[
"draw:transform" ] = aBuf.makeStringAndClear();
222 auto this_it = elem.
Children.begin();
223 while( this_it != elem.
Children.end() && this_it->get() != &elem )
225 (*this_it)->visitedBy( *
this, this_it );
248 for ( sal_uInt32 j = 0; j< b2dPolygon.
count(); j++ )
286 OUStringBuffer
aBuf( 64 );
287 aBuf.append(
"0 0 " );
291 aProps[
"svg:viewBox" ] = aBuf.makeStringAndClear();
313 auto this_it = elem.
Children.begin();
314 while( this_it != elem.
Children.end() && this_it->get() != &elem )
316 (*this_it)->visitedBy( *
this, this_it );
326 for(
const auto& rxChild : elem.
Children )
333 for(
auto child_it = pPage->
Children.begin(); child_it != pPage->
Children.end(); ++child_it )
335 if( dynamic_cast<DrawElement*>(child_it->get()) !=
nullptr )
336 (*child_it)->
visitedBy( *
this, child_it );
346 if( dynamic_cast<DrawElement*>(it->get()) ==
nullptr )
347 (*it)->visitedBy( *
this, it );
383 auto next_it = elemIt;
430 auto prev = rParentIt;
449 if( pPrevPara->
y + pPrevPara->
h + 2*head_line_height > elem.
y )
462 if( pPrevText && pThisText )
502 std::list< std::unique_ptr<Element> >::iterator page_element, next_page_element;
503 next_page_element = elem.
Children.begin();
504 double fCurLineHeight = 0.0;
505 int nCurLineElements = 0;
506 double line_left = elem.
w, line_right = 0.0;
507 double column_width = elem.
w*0.75;
509 while( next_page_element != elem.
Children.end() )
511 page_element = next_page_element++;
515 pCurPara = pPagePara;
517 fCurLineHeight = 0.0;
518 nCurLineElements = 0;
519 for(
const auto& rxChild : pCurPara->
Children )
524 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pTestText->
h)/
double(nCurLineElements+1);
533 if( ! pDraw && pLink && ! pLink->
Children.empty() )
534 pDraw = dynamic_cast<DrawElement*>(pLink->
Children.front().get() );
539 bool bInsertToParagraph =
false;
541 if( pCurPara && pDraw->
y < pCurPara->
y + pCurPara->
h )
543 if( pDraw->
h < fCurLineHeight * 1.5 )
545 bInsertToParagraph =
true;
546 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pDraw->
h)/
double(nCurLineElements+1);
553 else if( next_page_element != elem.
Children.end() )
559 if( pPara && ! pPara->
Children.empty() )
560 pText = dynamic_cast<TextElement*>(pPara->
Children.front().get());
563 pDraw->
h < pText->
h*1.5 &&
565 ( ( pDraw->
y >= pText->
y && pDraw->
y <= pText->
y+pText->
h ) ||
566 ( pDraw->
y+pDraw->
h >= pText->
y && pDraw->
y+pDraw->
h <= pText->
y+pText->
h )
570 bInsertToParagraph =
true;
571 fCurLineHeight = pDraw->
h;
572 nCurLineElements = 1;
573 line_left = pDraw->
x;
574 line_right = pDraw->
x + pDraw->
w;
582 if( ! bInsertToParagraph )
590 if( ! pText && pLink && ! pLink->
Children.empty() )
591 pText = dynamic_cast<TextElement*>(pLink->
Children.front().get());
595 static_cast<Element*>(pText);
599 if( nCurLineElements > 0 )
603 if( pGeo->
y > pCurPara->
y+pCurPara->
h + fCurLineHeight*0.5 )
605 else if( pGeo->
y > (pCurPara->
y+pCurPara->
h - fCurLineHeight*0.05) )
609 if( (line_right - line_left) < pCurPara->
w*0.75 )
612 else if( (line_right - line_left) < column_width*0.75 )
620 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pGeo->
h)/
double(nCurLineElements+1);
622 if( pGeo->
x < line_left )
624 if( pGeo->
x+pGeo->
w > line_right )
625 line_right = pGeo->
x+pGeo->
w;
629 fCurLineHeight = pGeo->
h;
630 nCurLineElements = 1;
632 line_right = pGeo->
x + pGeo->
w;
643 page_element = elem.
Children.insert( page_element, std::unique_ptr<Element>(pCurPara) );
647 next_page_element = page_element;
648 ++ next_page_element;
650 Element* pCurEle = page_element->get();
652 OSL_ENSURE( !pText || pCurEle == pText || pCurEle == pLink,
"paragraph child list in disorder" );
675 auto isParagraphElement = [](std::unique_ptr<Element>& rxChild) ->
bool {
682 auto it = std::find_if(rElem.
Children.begin(), rElem.
Children.end(), isParagraphElement);
690 while( ++next_it != rElem.
Children.end() && pNextPara == nullptr )
694 if( pNextPara && pNextPara->
y > rPara.
y+rPara.
h*2 )
704 auto rit = std::find_if(rElem.
Children.rbegin(), rElem.
Children.rend(), isParagraphElement);
712 std::list< std::unique_ptr<Element> >::reverse_iterator next_it = rit;
714 while( ++next_it != rElem.
Children.rend() && pNextPara == nullptr )
718 if( pNextPara && pNextPara->
y < rPara.
y-rPara.
h*2 )
730 OSL_FAIL(
"empty paragraph optimized" );
735 auto next = rParent.
Children.begin();
738 bool bRotatedFrame =
false;
743 bRotatedFrame =
true;
745 while( next != rParent.
Children.end() )
747 bool bConcat =
false;
762 && ! pNext->
Text.isEmpty()
763 && pNext->
Text[0] !=
' '
764 && ! pCur->
Text.isEmpty()
765 && pCur->
Text[pCur->
Text.getLength() - 1] !=
' '
769 if( pNext->
y > pCur->
y+pCur->
h )
775 || aLastCode == 0x2010
776 || (aLastCode >= 0x2012 && aLastCode <= 0x2015)
777 || aLastCode == 0xff0d
781 pCur->
Text.setLength( pCur->
Text.getLength()-1 );
784 else if( aLastCode != 0x2011 )
786 pCur->
Text.append(
' ' );
793 if( pCur->
x + pCur->
w + pNext->
h*0.15 < pNext->
x )
795 pCur->
Text.append(
' ' );
822 else if( dynamic_cast<HyperlinkElement*>(it->get()) )
848 aProps[
"style:family" ] =
"graphic";
856 aGCProps[
"draw:stroke" ] =
"solid";
864 aGCProps[
"draw:stroke" ] =
"dash";
865 aGCProps[
"draw:stroke-dash" ] =
877 aGCProps[
"draw:stroke" ] =
"none";
883 aGCProps[
"draw:fill" ] =
"solid";
888 aGCProps[
"draw:fill" ] =
"none";
893 aStyle.
SubStyles.push_back( &aSubStyle );
906 aProps[
"style:family" ] =
"text";
913 aFontProps[
"fo:font-family" ] = rFont.
familyName;
914 aFontProps[
"style:font-family-asia" ] = rFont.
familyName;
915 aFontProps[
"style:font-family-complex" ] = rFont.
familyName;
918 aFontProps[
"fo:font-weight" ] = rFont.
fontWeight;
919 aFontProps[
"style:font-weight-asian" ] = rFont.
fontWeight;
920 aFontProps[
"style:font-weight-complex" ] = rFont.
fontWeight;
925 aFontProps[
"fo:font-style" ] =
"italic";
926 aFontProps[
"style:font-style-asian" ] =
"italic";
927 aFontProps[
"style:font-style-complex" ] =
"italic";
933 aFontProps[
"style:text-underline-style" ] =
"solid";
934 aFontProps[
"style:text-underline-width" ] =
"auto";
935 aFontProps[
"style:text-underline-color" ] =
"font-color";
940 aFontProps[
"style:text-outline" ] =
"true";
944 aFontProps[
"fo:font-size" ] = aFSize;
945 aFontProps[
"style:font-size-asian" ] = aFSize;
946 aFontProps[
"style:font-size-complex" ] = aFSize;
954 aStyle.
SubStyles.push_back( &aSubStyle );
975 bool bIsCenter =
false;
976 if( elem.
w < ( p_w/2) )
978 double delta = elem.
w/4;
983 if( fabs( elem.
x+elem.
w/2 - ( p_x+ p_w/2) ) < delta ||
984 (pPage && fabs( elem.
x+elem.
w/2 - (pPage->
x + pPage->
w/2) ) < delta) )
987 aParaProps[
"fo:text-align" ] =
"center";
990 if( ! bIsCenter && elem.
x > p_x + p_w/10 )
993 OUStringBuffer
aBuf( 32 );
996 aParaProps[
"fo:margin-left" ] = aBuf.makeStringAndClear();
1001 auto it = rParentIt;
1004 pNextPara = dynamic_cast< const ParagraphElement* >(it->get());
1009 OUStringBuffer
aBuf( 32 );
1010 aBuf.append(
convPx2mm( pNextPara->
y - (elem.
y+elem.
h) ) );
1011 aBuf.append(
"mm" );
1012 aParaProps[
"fo:margin-bottom" ] = aBuf.makeStringAndClear();
1017 if( ! aParaProps.empty() )
1020 aProps[
"style:family" ] =
"paragraph";
1023 aStyle.
SubStyles.push_back( &aSubStyle );
1033 aProps[
"style:family" ] =
"graphic";
1037 aGCProps[
"draw:stroke" ] =
"none";
1038 aGCProps[
"draw:fill" ] =
"none";
1039 aGCProps[
"draw:auto-grow-height" ] =
"true";
1040 aGCProps[
"draw:auto-grow-width" ] =
"true";
1041 aGCProps[
"draw:textarea-horizontal-align" ] =
"left";
1042 aGCProps[
"draw:textarea-vertical-align" ] =
"top";
1043 aGCProps[
"fo:min-height"] =
"0cm";
1044 aGCProps[
"fo:min-width"] =
"0cm";
1045 aGCProps[
"fo:padding-top" ] =
"0cm";
1046 aGCProps[
"fo:padding-left" ] =
"0cm";
1047 aGCProps[
"fo:padding-right" ] =
"0cm";
1048 aGCProps[
"fo:padding-bottom" ] =
"0cm";
1052 aStyle.
SubStyles.push_back( &aSubStyle );
1064 const OUString& rMasterPageName )
1074 aProps[
"style:family" ] =
"paragraph";
1075 aProps[
"style:master-page-name" ] = rMasterPageName;
1101 for(
const auto& rxChild : elem.
Children )
1103 if( dynamic_cast<ParagraphElement*>( rxChild.get() ) )
1109 if( rxChild->x + rxChild->w > elem.
w - elem.
RightMargin )
1137 left_margin = rtl_math_round( left_margin, 0, rtl_math_RoundingMode_Floor );
1138 top_margin = rtl_math_round( top_margin, 0, rtl_math_RoundingMode_Floor );
1140 right_margin = rtl_math_round( right_margin, right_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1141 bottom_margin = rtl_math_round( bottom_margin, bottom_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1145 if( left_margin > page_width/2.0 - 10 )
1147 if( right_margin > page_width/2.0 - 10 )
1149 if( top_margin > page_height/2.0 - 10 )
1151 if( bottom_margin > page_height/2.0 - 10 )
1155 if( left_margin < 0 )
1157 if( right_margin < 0 )
1159 if( top_margin < 0 )
1161 if( bottom_margin < 0 )
1165 if( right_margin > left_margin*1.5 )
1166 right_margin = left_margin;
1176 aPageLayoutProps[
"fo:page-width" ] =
unitMMString( page_width );
1177 aPageLayoutProps[
"fo:page-height" ] =
unitMMString( page_height );
1178 aPageLayoutProps[
"style:print-orientation" ]
1179 = elem.
w < elem.
h ? std::u16string_view(
u"portrait") : std::u16string_view(
u"landscape");
1180 aPageLayoutProps[
"fo:margin-top" ] =
unitMMString( top_margin );
1181 aPageLayoutProps[
"fo:margin-bottom" ] =
unitMMString( bottom_margin );
1182 aPageLayoutProps[
"fo:margin-left" ] =
unitMMString( left_margin );
1183 aPageLayoutProps[
"fo:margin-right" ] =
unitMMString( right_margin );
1184 aPageLayoutProps[
"style:writing-mode" ]=
"lr-tb";
1193 aPageProps[
"style:page-layout-name" ] = aMasterPageLayoutName;
1199 elem.
HeaderElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1201 aMPStyle.
SubStyles.push_back( &aHeaderStyle );
1205 elem.
FooterElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1207 aMPStyle.
SubStyles.push_back( &aFooterStyle );
1221 pFirstPara->
Parent = &elem;
1222 elem.
Children.push_front( std::unique_ptr<Element>(pFirstPara) );
css::rendering::ARGBColor LineColor
std::unordered_map< OUString, OUString > PropertyMap
StyleContainer & m_rStyleContainer
basegfx::B2DPolyPolygon PolyPoly
basegfx::B2DPoint getNextControlPoint(sal_uInt32 nIndex) const
bool isRotatedOrSkewed() const
OUString unitMMString(double fMM)
static void fillFrameProps(DrawElement &rElem, PropertyMap &rProps, const EmitContext &rEmitContext)
#define PDFI_OUTDEV_RESOLUTION
double convmm2Px(double fMM)
bool isSingleLined(PDFIProcessor const &rProc) const
std::vector< Style * > SubStyles
void applyToChildren(ElementTreeVisitor &)
Apply visitor to all children.
static ParagraphElement * createParagraphElement(Element *pParent)
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
virtual void beginTag(const char *pTag, const PropertyMap &rProperties)=0
Open up a tag with the given properties.
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
OUString convertPixelToUnitString(double fPix)
void setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon &rPolygon)
sal_Int32 impl_getStyleId(const Style &rStyle, bool bSubStyle)
Element * ContainedElement
const FontAttributes & getFont(sal_Int32 nFontId) const
B2DPolygon const & getB2DPolygon(sal_uInt32 nIndex) const
basegfx::B2DPolyPolygon Clip
PDFIProcessor & rProcessor
bool isPrevControlPointUsed(sal_uInt32 nIndex) const
std::unique_ptr< Element > HeaderElement
TextElement * getFirstTextChild() const
void setB2DPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
css::rendering::ARGBColor FillColor
const GraphicsContext & getGraphicsContext(sal_Int32 nGCId) const
double convPx2mm(double fPix)
void optimizeTextElements(Element &rParent)
std::vector< double > DashArray
std::unique_ptr< Element > FooterElement
sal_Int32 getGCId(const GraphicsContext &rGC)
const PropertyMap * getProperties(sal_Int32 nStyleId) const
css::uno::Reference< css::task::XStatusIndicator > xStatusIndicator
std::list< std::unique_ptr< Element > > Children
OUString GetLineJoinString() const
virtual void visit(HyperlinkElement &, const std::list< std::unique_ptr< Element > >::const_iterator &) override
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
double GetAverageTransformationScale(const basegfx::B2DHomMatrix &matrix)
basegfx::B2DHomMatrix Transformation
void resolveFontStyles(PDFIProcessor const &rProc)
OUString getStyleName(sal_Int32 nStyle) const
OUString getColorString(const css::rendering::ARGBColor &)
Convert color to "#FEFEFE" color notation.
EmitContext & m_rEmitContext
basegfx::B2DPoint getPrevControlPoint(sal_uInt32 nIndex) const
sal_Int32 setProperties(sal_Int32 nStyleId, PropertyMap &&rNewProps)
void setNextControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
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 FillDashStyleProps(PropertyMap &props, const std::vector< double > &dashArray, double scale)
PDFIProcessor & m_rProcessor
exports com.sun.star. style
static void setFirstOnPage(ParagraphElement &rElem, StyleContainer &rStyles, const OUString &rMasterPageName)
const css::uno::Reference< css::task::XStatusIndicator > & getStatusIndicator() const
bool isNextControlPointUsed(sal_uInt32 nIndex) const
void updateGeometryWith(const Element *pMergeFrom)
Union element geometry with given element.
void checkHeaderAndFooter(PageElement &rElem)
#define SAL_INFO(area, stream)
double convPx2mmPrec2(double fPix)
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 ...
sal_Int32 getStyleId(const Style &rStyle)
static void sortElements(Element *pElement)
OUString exportToSvgD(const B2DPolyPolygon &rPolyPoly, bool bUseRelativeCoordinates, bool bDetectQuadraticBeziers, bool bHandleRelativeNextPointCompatible, bool bOOXMLMotionPath=false)
double getLineHeight(PDFIProcessor &rProc) const
void writeBase64EncodedStream(ImageId nImageId, EmitContext &rContext)
OUString GetLineCapString() const
virtual void write(const OUString &rString)=0
Write PCTEXT as-is to output.
void setPrevControlPoint(sal_uInt32 nIndex, const basegfx::B2DPoint &rValue)
PDFIProcessor & m_rProcessor
virtual void endTag(const char *pTag)=0
Close previously opened tag.
basegfx::B2DPoint const & getB2DPoint(sal_uInt32 nIndex) const