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 ? OUStringLiteral(
u"character") : OUStringLiteral(
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 )
493 std::list< std::unique_ptr<Element> >::iterator page_element, next_page_element;
494 next_page_element = elem.
Children.begin();
495 double fCurLineHeight = 0.0;
496 int nCurLineElements = 0;
497 double line_left = elem.
w, line_right = 0.0;
498 double column_width = elem.
w*0.75;
500 while( next_page_element != elem.
Children.end() )
502 page_element = next_page_element++;
506 pCurPara = pPagePara;
508 fCurLineHeight = 0.0;
509 nCurLineElements = 0;
510 for(
const auto& rxChild : pCurPara->
Children )
515 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pTestText->
h)/
double(nCurLineElements+1);
524 if( ! pDraw && pLink && ! pLink->
Children.empty() )
525 pDraw = dynamic_cast<DrawElement*>(pLink->
Children.front().get() );
530 bool bInsertToParagraph =
false;
532 if( pCurPara && pDraw->
y < pCurPara->
y + pCurPara->
h )
534 if( pDraw->
h < fCurLineHeight * 1.5 )
536 bInsertToParagraph =
true;
537 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pDraw->
h)/
double(nCurLineElements+1);
544 else if( next_page_element != elem.
Children.end() )
550 if( pPara && ! pPara->
Children.empty() )
551 pText = dynamic_cast<TextElement*>(pPara->
Children.front().get());
554 pDraw->
h < pText->
h*1.5 &&
556 ( ( pDraw->
y >= pText->
y && pDraw->
y <= pText->
y+pText->
h ) ||
557 ( pDraw->
y+pDraw->
h >= pText->
y && pDraw->
y+pDraw->
h <= pText->
y+pText->
h )
561 bInsertToParagraph =
true;
562 fCurLineHeight = pDraw->
h;
563 nCurLineElements = 1;
564 line_left = pDraw->
x;
565 line_right = pDraw->
x + pDraw->
w;
573 if( ! bInsertToParagraph )
581 if( ! pText && pLink && ! pLink->
Children.empty() )
582 pText = dynamic_cast<TextElement*>(pLink->
Children.front().get());
586 static_cast<Element*>(pText);
590 if( nCurLineElements > 0 )
594 if( pGeo->
y > pCurPara->
y+pCurPara->
h + fCurLineHeight*0.5 )
596 else if( pGeo->
y > (pCurPara->
y+pCurPara->
h - fCurLineHeight*0.05) )
600 if( (line_right - line_left) < pCurPara->
w*0.75 )
603 else if( (line_right - line_left) < column_width*0.75 )
611 fCurLineHeight = (fCurLineHeight*double(nCurLineElements) + pGeo->
h)/
double(nCurLineElements+1);
613 if( pGeo->
x < line_left )
615 if( pGeo->
x+pGeo->
w > line_right )
616 line_right = pGeo->
x+pGeo->
w;
620 fCurLineHeight = pGeo->
h;
621 nCurLineElements = 1;
623 line_right = pGeo->
x + pGeo->
w;
634 page_element = elem.
Children.insert( page_element, std::unique_ptr<Element>(pCurPara) );
638 next_page_element = page_element;
639 ++ next_page_element;
641 Element* pCurEle = page_element->get();
643 OSL_ENSURE( !pText || pCurEle == pText || pCurEle == pLink,
"paragraph child list in disorder" );
666 auto isParagraphElement = [](std::unique_ptr<Element>& rxChild) ->
bool {
673 auto it = std::find_if(rElem.
Children.begin(), rElem.
Children.end(), isParagraphElement);
681 while( ++next_it != rElem.
Children.end() && pNextPara == nullptr )
685 if( pNextPara && pNextPara->
y > rPara.
y+rPara.
h*2 )
695 auto rit = std::find_if(rElem.
Children.rbegin(), rElem.
Children.rend(), isParagraphElement);
703 std::list< std::unique_ptr<Element> >::reverse_iterator next_it = rit;
705 while( ++next_it != rElem.
Children.rend() && pNextPara == nullptr )
709 if( pNextPara && pNextPara->
y < rPara.
y-rPara.
h*2 )
721 OSL_FAIL(
"empty paragraph optimized" );
726 auto next = rParent.
Children.begin();
729 bool bRotatedFrame =
false;
734 bRotatedFrame =
true;
736 while( next != rParent.
Children.end() )
738 bool bConcat =
false;
753 && ! pNext->
Text.isEmpty()
754 && pNext->
Text[0] !=
' '
755 && ! pCur->
Text.isEmpty()
756 && pCur->
Text[pCur->
Text.getLength() - 1] !=
' '
760 if( pNext->
y > pCur->
y+pCur->
h )
766 || aLastCode == 0x2010
767 || (aLastCode >= 0x2012 && aLastCode <= 0x2015)
768 || aLastCode == 0xff0d
772 pCur->
Text.setLength( pCur->
Text.getLength()-1 );
775 else if( aLastCode != 0x2011 )
777 pCur->
Text.append(
' ' );
784 if( pCur->
x + pCur->
w + pNext->
h*0.15 < pNext->
x )
786 pCur->
Text.append(
' ' );
813 else if( dynamic_cast<HyperlinkElement*>(it->get()) )
839 aProps[
"style:family" ] =
"graphic";
847 aGCProps[
"draw:stroke" ] =
"solid";
855 aGCProps[
"draw:stroke" ] =
"dash";
856 aGCProps[
"draw:stroke-dash" ] =
868 aGCProps[
"draw:stroke" ] =
"none";
874 aGCProps[
"draw:fill" ] =
"solid";
879 aGCProps[
"draw:fill" ] =
"none";
884 aStyle.
SubStyles.push_back( &aSubStyle );
897 aProps[
"style:family" ] =
"text";
902 aFontProps[
"fo:font-family" ] = rFont.
familyName;
906 aFontProps[
"fo:font-weight" ] =
"bold";
907 aFontProps[
"fo:font-weight-asian" ] =
"bold";
908 aFontProps[
"fo:font-weight-complex" ] =
"bold";
913 aFontProps[
"fo:font-style" ] =
"italic";
914 aFontProps[
"fo:font-style-asian" ] =
"italic";
915 aFontProps[
"fo:font-style-complex" ] =
"italic";
920 aFontProps[
"style:text-underline-style" ] =
"solid";
921 aFontProps[
"style:text-underline-width" ] =
"auto";
922 aFontProps[
"style:text-underline-color" ] =
"font-color";
927 aFontProps[
"style:text-outline" ] =
"true";
931 aFontProps[
"fo:font-size" ] = aFSize;
932 aFontProps[
"style:font-size-asian" ] = aFSize;
933 aFontProps[
"style:font-size-complex" ] = aFSize;
940 aStyle.
SubStyles.push_back( &aSubStyle );
961 bool bIsCenter =
false;
962 if( elem.
w < ( p_w/2) )
964 double delta = elem.
w/4;
969 if( fabs( elem.
x+elem.
w/2 - ( p_x+ p_w/2) ) < delta ||
970 (pPage && fabs( elem.
x+elem.
w/2 - (pPage->
x + pPage->
w/2) ) < delta) )
973 aParaProps[
"fo:text-align" ] =
"center";
976 if( ! bIsCenter && elem.
x > p_x + p_w/10 )
979 OUStringBuffer
aBuf( 32 );
982 aParaProps[
"fo:margin-left" ] = aBuf.makeStringAndClear();
990 pNextPara = dynamic_cast< const ParagraphElement* >(it->get());
995 OUStringBuffer
aBuf( 32 );
996 aBuf.append(
convPx2mm( pNextPara->
y - (elem.
y+elem.
h) ) );
998 aParaProps[
"fo:margin-bottom" ] = aBuf.makeStringAndClear();
1003 if( ! aParaProps.empty() )
1006 aProps[
"style:family" ] =
"paragraph";
1009 aStyle.
SubStyles.push_back( &aSubStyle );
1019 aProps[
"style:family" ] =
"graphic";
1023 aGCProps[
"draw:stroke" ] =
"none";
1024 aGCProps[
"draw:fill" ] =
"none";
1025 aGCProps[
"draw:auto-grow-height" ] =
"true";
1026 aGCProps[
"draw:auto-grow-width" ] =
"true";
1027 aGCProps[
"draw:textarea-horizontal-align" ] =
"left";
1028 aGCProps[
"draw:textarea-vertical-align" ] =
"top";
1029 aGCProps[
"fo:min-height"] =
"0cm";
1030 aGCProps[
"fo:min-width"] =
"0cm";
1031 aGCProps[
"fo:padding-top" ] =
"0cm";
1032 aGCProps[
"fo:padding-left" ] =
"0cm";
1033 aGCProps[
"fo:padding-right" ] =
"0cm";
1034 aGCProps[
"fo:padding-bottom" ] =
"0cm";
1038 aStyle.
SubStyles.push_back( &aSubStyle );
1050 const OUString& rMasterPageName )
1060 aProps[
"style:family" ] =
"paragraph";
1061 aProps[
"style:master-page-name" ] = rMasterPageName;
1087 for(
const auto& rxChild : elem.
Children )
1089 if( dynamic_cast<ParagraphElement*>( rxChild.get() ) )
1095 if( rxChild->x + rxChild->w > elem.
w - elem.
RightMargin )
1123 left_margin = rtl_math_round( left_margin, 0, rtl_math_RoundingMode_Floor );
1124 top_margin = rtl_math_round( top_margin, 0, rtl_math_RoundingMode_Floor );
1126 right_margin = rtl_math_round( right_margin, right_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1127 bottom_margin = rtl_math_round( bottom_margin, bottom_margin >= 10 ? -1 : 0, rtl_math_RoundingMode_Floor );
1131 if( left_margin > page_width/2.0 - 10 )
1133 if( right_margin > page_width/2.0 - 10 )
1135 if( top_margin > page_height/2.0 - 10 )
1137 if( bottom_margin > page_height/2.0 - 10 )
1141 if( left_margin < 0 )
1143 if( right_margin < 0 )
1145 if( top_margin < 0 )
1147 if( bottom_margin < 0 )
1151 if( right_margin > left_margin*1.5 )
1152 right_margin = left_margin;
1162 aPageLayoutProps[
"fo:page-width" ] =
unitMMString( page_width );
1163 aPageLayoutProps[
"fo:page-height" ] =
unitMMString( page_height );
1164 aPageLayoutProps[
"style:print-orientation" ]
1165 = elem.
w < elem.
h ? std::u16string_view(
u"portrait") : std::u16string_view(
u"landscape");
1166 aPageLayoutProps[
"fo:margin-top" ] =
unitMMString( top_margin );
1167 aPageLayoutProps[
"fo:margin-bottom" ] =
unitMMString( bottom_margin );
1168 aPageLayoutProps[
"fo:margin-left" ] =
unitMMString( left_margin );
1169 aPageLayoutProps[
"fo:margin-right" ] =
unitMMString( right_margin );
1170 aPageLayoutProps[
"style:writing-mode" ]=
"lr-tb";
1179 aPageProps[
"style:page-layout-name" ] = aMasterPageLayoutName;
1185 elem.
HeaderElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1187 aMPStyle.
SubStyles.push_back( &aHeaderStyle );
1191 elem.
FooterElement->visitedBy( *
this, std::list<std::unique_ptr<Element>>::iterator() );
1193 aMPStyle.
SubStyles.push_back( &aFooterStyle );
1207 pFirstPara->
Parent = &elem;
1208 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
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
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
sal_Int32 setProperties(sal_Int32 nStyleId, const PropertyMap &rNewProps)
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
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)
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