LCOV - code coverage report
Current view: top level - svx/source/customshapes - EnhancedCustomShapeFontWork.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 402 504 79.8 %
Date: 2014-11-03 Functions: 27 28 96.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "EnhancedCustomShapeFontWork.hxx"
      21             : #include <svx/svddef.hxx>
      22             : #include <svx/svdogrp.hxx>
      23             : #include <svx/svdopath.hxx>
      24             : #include <vcl/metric.hxx>
      25             : #include <svx/svdpage.hxx>
      26             : #include <svx/sdasitm.hxx>
      27             : #include <svx/sdasaitm.hxx>
      28             : #include <svx/sdtfsitm.hxx>
      29             : #include <vcl/virdev.hxx>
      30             : #include <svx/svditer.hxx>
      31             : #include <editeng/eeitem.hxx>
      32             : #include <editeng/frmdiritem.hxx>
      33             : #include <editeng/fontitem.hxx>
      34             : #include <editeng/postitem.hxx>
      35             : #include <editeng/wghtitem.hxx>
      36             : #include <editeng/charscaleitem.hxx>
      37             : #include "svx/EnhancedCustomShapeTypeNames.hxx"
      38             : #include <svx/svdorect.hxx>
      39             : #include <svx/svdoashp.hxx>
      40             : #include <editeng/outliner.hxx>
      41             : #include <editeng/outlobj.hxx>
      42             : #include <editeng/editobj.hxx>
      43             : #include <editeng/editeng.hxx>
      44             : #include <o3tl/numeric.hxx>
      45             : #include <svx/svdmodel.hxx>
      46             : #include <vector>
      47             : #include <numeric>
      48             : #include <algorithm>
      49             : #include <comphelper/processfactory.hxx>
      50             : #include <com/sun/star/i18n/BreakIterator.hpp>
      51             : #include <com/sun/star/i18n/ScriptType.hpp>
      52             : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      53             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      54             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      55             : #include <basegfx/polygon/b2dpolygontools.hxx>
      56             : 
      57             : using namespace com::sun::star;
      58             : using namespace com::sun::star::uno;
      59             : 
      60         592 : struct FWCharacterData                  // representing a single character
      61             : {
      62             :     std::vector< tools::PolyPolygon >          vOutlines;
      63             :     Rectangle                           aBoundRect;
      64             : };
      65         996 : struct FWParagraphData                  // representing a single paragraph
      66             : {
      67             :     OUString                       aString;
      68             :     std::vector< FWCharacterData >      vCharacters;
      69             :     Rectangle                           aBoundRect;
      70             :     sal_Int16                           nFrameDirection;
      71             : };
      72         516 : struct FWTextArea                       // representing multiple concluding paragraphs
      73             : {
      74             :     std::vector< FWParagraphData >      vParagraphs;
      75             :     Rectangle                           aBoundRect;
      76             : };
      77         216 : struct FWData                           // representing the whole text
      78             : {
      79             :     std::vector< FWTextArea >           vTextAreas;
      80             :     double                              fHorizontalTextScaling;
      81             :     sal_uInt32                          nMaxParagraphsPerTextArea;
      82             :     sal_Int32                           nSingleLineHeight;
      83             :     bool                            bSingleLineMode;
      84             : };
      85             : 
      86             : 
      87         108 : static bool InitializeFontWorkData( const SdrObject* pCustomShape, const sal_uInt16 nOutlinesCount2d, FWData& rFWData )
      88             : {
      89         108 :     bool bNoErr = false;
      90         108 :     bool bSingleLineMode = false;
      91         108 :     sal_uInt16 nTextAreaCount = nOutlinesCount2d;
      92         108 :     if ( nOutlinesCount2d & 1 )
      93          26 :         bSingleLineMode = true;
      94             :     else
      95          82 :         nTextAreaCount >>= 1;
      96             : 
      97         108 :     if ( nTextAreaCount )
      98             :     {
      99         108 :         rFWData.bSingleLineMode = bSingleLineMode;
     100             : 
     101             :         // setting the strings
     102         108 :         OutlinerParaObject* pParaObj = static_cast<const SdrObjCustomShape*>(pCustomShape)->GetOutlinerParaObject();
     103         108 :         if ( pParaObj )
     104             :         {
     105         108 :             const EditTextObject& rTextObj = pParaObj->GetTextObject();
     106         108 :             sal_Int32 nParagraphsLeft = rTextObj.GetParagraphCount();
     107             : 
     108         108 :             rFWData.nMaxParagraphsPerTextArea = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
     109         108 :             sal_Int32 j = 0;
     110         336 :             while( nParagraphsLeft && nTextAreaCount )
     111             :             {
     112         120 :                 FWTextArea aTextArea;
     113         120 :                 sal_Int32 i, nParagraphs = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
     114         272 :                 for ( i = 0; i < nParagraphs; ++i, ++j )
     115             :                 {
     116         152 :                     FWParagraphData aParagraphData;
     117         152 :                     aParagraphData.aString = rTextObj.GetText( j );
     118             : 
     119         152 :                     const SfxItemSet& rParaSet = rTextObj.GetParaAttribs( j );  // retrieving some paragraph attributes
     120         152 :                     aParagraphData.nFrameDirection = static_cast<const SvxFrameDirectionItem&>(rParaSet.Get( EE_PARA_WRITINGDIR )).GetValue();
     121         152 :                     aTextArea.vParagraphs.push_back( aParagraphData );
     122         152 :                 }
     123         120 :                 rFWData.vTextAreas.push_back( aTextArea );
     124         120 :                 nParagraphsLeft -= nParagraphs;
     125         120 :                 nTextAreaCount--;
     126         120 :             }
     127         108 :             bNoErr = true;
     128             :         }
     129             :     }
     130         108 :     return bNoErr;
     131             : }
     132             : 
     133         214 : double GetLength( const Polygon& rPolygon )
     134             : {
     135         214 :     double fLength = 0;
     136         214 :     if ( rPolygon.GetSize() > 1 )
     137             :     {
     138         214 :         sal_uInt16 nCount = rPolygon.GetSize();
     139        2884 :         while( --nCount )
     140        2456 :             fLength += ((Polygon&)rPolygon).CalcDistance( nCount, nCount - 1 );
     141             :     }
     142         214 :     return fLength;
     143             : }
     144             : 
     145             : 
     146             : /* CalculateHorizontalScalingFactor returns the horizontal scaling factor for
     147             : the whole text object, so that each text will match its corresponding 2d Outline */
     148         108 : void CalculateHorizontalScalingFactor( const SdrObject* pCustomShape,
     149             :                                         FWData& rFWData, const tools::PolyPolygon& rOutline2d )
     150             : {
     151         108 :     double fScalingFactor = 1.0;
     152         108 :     bool bScalingFactorDefined = false;
     153             : 
     154         108 :     sal_uInt16 i = 0;
     155         108 :     bool bSingleLineMode = false;
     156         108 :     sal_uInt16 nOutlinesCount2d = rOutline2d.Count();
     157             : 
     158         108 :     vcl::Font aFont;
     159         108 :     const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pCustomShape->GetMergedItem( EE_CHAR_FONTINFO ));
     160         108 :     aFont.SetHeight( pCustomShape->GetLogicRect().GetHeight() / rFWData.nMaxParagraphsPerTextArea );
     161         108 :     aFont.SetAlign( ALIGN_TOP );
     162         108 :     aFont.SetName( rFontItem.GetFamilyName() );
     163         108 :     aFont.SetFamily( rFontItem.GetFamily() );
     164         108 :     aFont.SetStyleName( rFontItem.GetStyleName() );
     165         108 :     aFont.SetOrientation( 0 );
     166             :     // initializing virtual device
     167             : 
     168         216 :     VirtualDevice aVirDev( 1 );
     169         108 :     aVirDev.SetMapMode( MAP_100TH_MM );
     170         108 :     aVirDev.SetFont( aFont );
     171             : 
     172         108 :     if ( nOutlinesCount2d & 1 )
     173          26 :         bSingleLineMode = true;
     174             : 
     175         108 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     176         108 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     177         336 :     while( aTextAreaIter != aTextAreaIEnd )
     178             :     {
     179             :         // calculating the width of the corresponding 2d text area
     180         120 :         double fWidth = GetLength( rOutline2d.GetObject( i++ ) );
     181         120 :         if ( !bSingleLineMode )
     182             :         {
     183          94 :             fWidth += GetLength( rOutline2d.GetObject( i++ ) );
     184          94 :             fWidth /= 2.0;
     185             :         }
     186         120 :         std::vector< FWParagraphData >::const_iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     187         120 :         std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     188         392 :         while( aParagraphIter != aParagraphIEnd )
     189             :         {
     190         152 :             double fTextWidth = aVirDev.GetTextWidth( aParagraphIter->aString );
     191         152 :             if ( fTextWidth > 0.0 )
     192             :             {
     193         148 :                 double fScale = fWidth / fTextWidth;
     194         148 :                 if ( !bScalingFactorDefined )
     195             :                 {
     196         108 :                     fScalingFactor = fScale;
     197         108 :                     bScalingFactorDefined = true;
     198             :                 }
     199             :                 else
     200             :                 {
     201          40 :                     if ( fScale < fScalingFactor )
     202          32 :                         fScalingFactor = fScale;
     203             :                 }
     204             :             }
     205         152 :             ++aParagraphIter;
     206             :         }
     207         120 :         ++aTextAreaIter;
     208             :     }
     209         216 :     rFWData.fHorizontalTextScaling = fScalingFactor;
     210         108 : }
     211             : 
     212         120 : void GetTextAreaOutline( const FWData& rFWData, const SdrObject* pCustomShape, FWTextArea& rTextArea, bool bSameLetterHeights )
     213             : {
     214         120 :     bool bIsVertical = static_cast<const SdrObjCustomShape*>(pCustomShape)->IsVerticalWriting();
     215         120 :     sal_Int32 nVerticalOffset = rFWData.nMaxParagraphsPerTextArea > rTextArea.vParagraphs.size()
     216         120 :                                     ? rFWData.nSingleLineHeight / 2 : 0;
     217             : 
     218         120 :     std::vector< FWParagraphData >::iterator aParagraphIter( rTextArea.vParagraphs.begin() );
     219         120 :     std::vector< FWParagraphData >::iterator aParagraphIEnd( rTextArea.vParagraphs.end() );
     220         392 :     while( aParagraphIter != aParagraphIEnd )
     221             :     {
     222         152 :         const OUString& rText = aParagraphIter->aString;
     223         152 :         if ( !rText.isEmpty() )
     224             :         {
     225             :             // generating vcl/font
     226         148 :             sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
     227         148 :             Reference< i18n::XBreakIterator > xBI( EnhancedCustomShapeFontWork::GetBreakIterator() );
     228         148 :             if ( xBI.is() )
     229             :             {
     230         148 :                 nScriptType = xBI->getScriptType( rText, 0 );
     231         148 :                 if( i18n::ScriptType::WEAK == nScriptType )
     232             :                 {
     233          12 :                     sal_Int32 nChg = xBI->endOfScript( rText, 0, nScriptType );
     234          12 :                     if (nChg < rText.getLength() && nChg >= 0)
     235          12 :                         nScriptType = xBI->getScriptType( rText, nChg );
     236             :                     else
     237           0 :                         nScriptType = i18n::ScriptType::LATIN;
     238             :                 }
     239             :             }
     240         148 :             sal_uInt16 nFntItm = EE_CHAR_FONTINFO;
     241         148 :             if ( nScriptType == i18n::ScriptType::COMPLEX )
     242           0 :                 nFntItm = EE_CHAR_FONTINFO_CTL;
     243         148 :             else if ( nScriptType == i18n::ScriptType::ASIAN )
     244           0 :                 nFntItm = EE_CHAR_FONTINFO_CJK;
     245         148 :             const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pCustomShape->GetMergedItem( nFntItm ));
     246         296 :             vcl::Font aFont;
     247         148 :             aFont.SetHeight( rFWData.nSingleLineHeight );
     248         148 :             aFont.SetAlign( ALIGN_TOP );
     249             : 
     250         148 :             aFont.SetName( rFontItem.GetFamilyName() );
     251         148 :             aFont.SetFamily( rFontItem.GetFamily() );
     252         148 :             aFont.SetStyleName( rFontItem.GetStyleName() );
     253         148 :             aFont.SetOrientation( 0 );
     254             : 
     255         148 :             const SvxPostureItem& rPostureItem = static_cast<const SvxPostureItem&>(pCustomShape->GetMergedItem( EE_CHAR_ITALIC ));
     256         148 :             aFont.SetItalic( rPostureItem.GetPosture() );
     257             : 
     258         148 :             const SvxWeightItem& rWeightItem = static_cast<const SvxWeightItem&>(pCustomShape->GetMergedItem( EE_CHAR_WEIGHT ));
     259         148 :             aFont.SetWeight( rWeightItem.GetWeight() );
     260             : 
     261             :             // initializing virtual device
     262         296 :             VirtualDevice aVirDev( 1 );
     263         148 :             aVirDev.SetMapMode( MAP_100TH_MM );
     264         148 :             aVirDev.SetFont( aFont );
     265         148 :             aVirDev.EnableRTL( true );
     266         148 :             if ( aParagraphIter->nFrameDirection == FRMDIR_HORI_RIGHT_TOP )
     267           0 :                 aVirDev.SetLayoutMode( TEXT_LAYOUT_BIDI_RTL );
     268             : 
     269         148 :             const SvxCharScaleWidthItem& rCharScaleWidthItem = static_cast<const SvxCharScaleWidthItem&>(pCustomShape->GetMergedItem( EE_CHAR_FONTWIDTH ));
     270         148 :             sal_uInt16 nCharScaleWidth = rCharScaleWidthItem.GetValue();
     271         148 :             long* pDXArry = NULL;
     272         148 :             sal_Int32 nWidth = 0;
     273             : 
     274             :             // VERTICAL
     275         148 :             if ( bIsVertical )
     276             :             {
     277             :                 // vertical _> each single character needs to be rotated by 90
     278             :                 sal_Int32 i;
     279           0 :                 sal_Int32 nHeight = 0;
     280           0 :                 Rectangle aSingleCharacterUnion;
     281           0 :                 for ( i = 0; i < rText.getLength(); i++ )
     282             :                 {
     283           0 :                     FWCharacterData aCharacterData;
     284           0 :                     OUString aCharText( (sal_Unicode)rText[ i ] );
     285           0 :                     if ( aVirDev.GetTextOutlines( aCharacterData.vOutlines, aCharText, 0, 0, -1, true, nWidth, pDXArry ) )
     286             :                     {
     287           0 :                         sal_Int32 nTextWidth = aVirDev.GetTextWidth( aCharText);
     288           0 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterData.vOutlines.begin();
     289           0 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterData.vOutlines.end();
     290           0 :                         if ( aOutlineIter == aOutlineIEnd )
     291             :                         {
     292           0 :                             nHeight += rFWData.nSingleLineHeight;
     293             :                         }
     294             :                         else
     295             :                         {
     296           0 :                             while ( aOutlineIter != aOutlineIEnd )
     297             :                             {
     298             :                                 // rotating
     299           0 :                                 aOutlineIter->Rotate( Point( nTextWidth / 2, rFWData.nSingleLineHeight / 2 ), 900 );
     300           0 :                                 aCharacterData.aBoundRect.Union( aOutlineIter->GetBoundRect() );
     301           0 :                                 ++aOutlineIter;
     302             :                             }
     303           0 :                             aOutlineIter = aCharacterData.vOutlines.begin();
     304           0 :                             aOutlineIEnd = aCharacterData.vOutlines.end();
     305           0 :                             while ( aOutlineIter != aOutlineIEnd )
     306             :                             {
     307           0 :                                 sal_Int32 nM = - aCharacterData.aBoundRect.Left() + nHeight;
     308           0 :                                 aOutlineIter->Move( nM, 0 );
     309           0 :                                 aCharacterData.aBoundRect.Move( nM, 0 );
     310           0 :                                 ++aOutlineIter;
     311             :                             }
     312           0 :                             nHeight += aCharacterData.aBoundRect.GetWidth() + ( rFWData.nSingleLineHeight / 5 );
     313           0 :                             aSingleCharacterUnion.Union( aCharacterData.aBoundRect );
     314             :                         }
     315             :                     }
     316           0 :                     aParagraphIter->vCharacters.push_back( aCharacterData );
     317           0 :                 }
     318           0 :                 std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     319           0 :                 std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     320           0 :                 while ( aCharacterIter != aCharacterIEnd )
     321             :                 {
     322           0 :                     std::vector< tools::PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
     323           0 :                     std::vector< tools::PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
     324           0 :                     while ( aOutlineIter != aOutlineIEnd )
     325             :                     {
     326           0 :                         aOutlineIter->Move( ( aSingleCharacterUnion.GetWidth() - aCharacterIter->aBoundRect.GetWidth() ) / 2, 0 );
     327           0 :                         ++aOutlineIter;
     328             :                     }
     329           0 :                     ++aCharacterIter;
     330             :                 }
     331             :             }
     332             :             else
     333             :             {
     334         148 :                 if ( ( nCharScaleWidth != 100 ) && nCharScaleWidth )
     335             :                 {   // applying character spacing
     336           0 :                     pDXArry = new long[ rText.getLength() ];
     337           0 :                     aVirDev.GetTextArray( rText, pDXArry);
     338           0 :                     FontMetric aFontMetric( aVirDev.GetFontMetric() );
     339           0 :                     aFont.SetWidth( (sal_Int32)( (double)aFontMetric.GetWidth() * ( (double)100 / (double)nCharScaleWidth ) ) );
     340           0 :                     aVirDev.SetFont( aFont );
     341             :                 }
     342         148 :                 FWCharacterData aCharacterData;
     343         148 :                 if ( aVirDev.GetTextOutlines( aCharacterData.vOutlines, rText, 0, 0, -1, true, nWidth, pDXArry ) )
     344             :                 {
     345         148 :                     aParagraphIter->vCharacters.push_back( aCharacterData );
     346         148 :                 }
     347             :             }
     348         148 :             delete[] pDXArry;
     349             : 
     350             :             // veritcal alignment
     351         148 :             std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     352         148 :             std::vector< FWCharacterData >::iterator aCharacterIEnd ( aParagraphIter->vCharacters.end() );
     353         444 :             while ( aCharacterIter != aCharacterIEnd )
     354             :             {
     355         148 :                 std::vector< tools::PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
     356         148 :                 std::vector< tools::PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
     357        1948 :                 while( aOutlineIter != aOutlineIEnd )
     358             :                 {
     359             : 
     360        1652 :                     tools::PolyPolygon& rPolyPoly = *aOutlineIter++;
     361             : 
     362        1652 :                     if ( nVerticalOffset )
     363         354 :                         rPolyPoly.Move( 0, nVerticalOffset );
     364             : 
     365             :                     // retrieving the boundrect for the paragraph
     366        1652 :                     Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
     367        1652 :                     aParagraphIter->aBoundRect.Union( aBoundRect );
     368             :                 }
     369         148 :                 ++aCharacterIter;
     370         148 :             }
     371             :         }
     372             :         // updating the boundrect for the text area by merging the current paragraph boundrect
     373         152 :         if ( aParagraphIter->aBoundRect.IsEmpty() )
     374             :         {
     375           4 :             if ( rTextArea.aBoundRect.IsEmpty() )
     376           0 :                 rTextArea.aBoundRect = Rectangle( Point( 0, 0 ), Size( 1, rFWData.nSingleLineHeight ) );
     377             :             else
     378           4 :                 rTextArea.aBoundRect.Bottom() += rFWData.nSingleLineHeight;
     379             :         }
     380             :         else
     381             :         {
     382         148 :             Rectangle& rParagraphBoundRect = aParagraphIter->aBoundRect;
     383         148 :             rTextArea.aBoundRect.Union( rParagraphBoundRect );
     384             : 
     385         148 :             if ( bSameLetterHeights )
     386             :             {
     387           0 :                 std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     388           0 :                 std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     389           0 :                 while ( aCharacterIter != aCharacterIEnd )
     390             :                 {
     391           0 :                     std::vector< tools::PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
     392           0 :                     std::vector< tools::PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
     393           0 :                     while( aOutlineIter != aOutlineIEnd )
     394             :                     {
     395           0 :                         Rectangle aPolyPolyBoundRect( aOutlineIter->GetBoundRect() );
     396           0 :                         if (aPolyPolyBoundRect.GetHeight() != rParagraphBoundRect.GetHeight() && aPolyPolyBoundRect.GetHeight())
     397           0 :                             aOutlineIter->Scale( 1.0, (double)rParagraphBoundRect.GetHeight() / aPolyPolyBoundRect.GetHeight() );
     398           0 :                         aPolyPolyBoundRect = aOutlineIter->GetBoundRect();
     399           0 :                         sal_Int32 nMove = aPolyPolyBoundRect.Top() - rParagraphBoundRect.Top();
     400           0 :                         if ( nMove )
     401           0 :                             aOutlineIter->Move( 0, -nMove );
     402           0 :                         ++aOutlineIter;
     403             :                     }
     404           0 :                     ++aCharacterIter;
     405             :                 }
     406             :             }
     407             :         }
     408         152 :         if ( bIsVertical )
     409           0 :             nVerticalOffset -= rFWData.nSingleLineHeight;
     410             :         else
     411         152 :             nVerticalOffset += rFWData.nSingleLineHeight;
     412         152 :         ++aParagraphIter;
     413             :     }
     414         120 : }
     415             : 
     416         108 : void GetFontWorkOutline( FWData& rFWData, const SdrObject* pCustomShape )
     417             : {
     418         108 :     SdrTextHorzAdjust eHorzAdjust( static_cast<const SdrTextHorzAdjustItem&>(pCustomShape->GetMergedItem( SDRATTR_TEXT_HORZADJUST )).GetValue() );
     419         108 :     SdrFitToSizeType  eFTS( static_cast<const SdrTextFitToSizeTypeItem&>(pCustomShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
     420             : 
     421         108 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     422         108 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     423             : 
     424         108 :     rFWData.nSingleLineHeight = (sal_Int32)( ( (double)pCustomShape->GetLogicRect().GetHeight()
     425         108 :                                                 / rFWData.nMaxParagraphsPerTextArea ) * rFWData.fHorizontalTextScaling );
     426             : 
     427         108 :     bool bSameLetterHeights = false;
     428         108 :     const SdrCustomShapeGeometryItem& rGeometryItem = static_cast<const SdrCustomShapeGeometryItem&>(pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
     429         108 :     const com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "SameLetterHeights" );
     430         108 :     if ( pAny )
     431         108 :         *pAny >>= bSameLetterHeights;
     432             : 
     433         336 :     while ( aTextAreaIter != aTextAreaIEnd )
     434             :     {
     435         120 :         GetTextAreaOutline( rFWData, pCustomShape, *aTextAreaIter, bSameLetterHeights );
     436         120 :         if ( eFTS == SDRTEXTFIT_ALLLINES )
     437             :         {
     438           0 :             std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     439           0 :             std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     440           0 :             while ( aParagraphIter != aParagraphIEnd )
     441             :             {
     442           0 :                 sal_Int32 nParaWidth = aParagraphIter->aBoundRect.GetWidth();
     443           0 :                 if ( nParaWidth )
     444             :                 {
     445           0 :                     double fScale = (double)aTextAreaIter->aBoundRect.GetWidth() / nParaWidth;
     446             : 
     447           0 :                     std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     448           0 :                     std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     449           0 :                     while ( aCharacterIter != aCharacterIEnd )
     450             :                     {
     451           0 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     452           0 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     453           0 :                         while( aOutlineIter != aOutlineIEnd )
     454             :                         {
     455           0 :                             aOutlineIter->Scale( fScale, 1.0 );
     456           0 :                             ++aOutlineIter;
     457             :                         }
     458           0 :                         ++aCharacterIter;
     459             :                     }
     460             :                 }
     461           0 :                 ++aParagraphIter;
     462             :             }
     463             :         }
     464             :         else
     465             :         {
     466         120 :             switch( eHorzAdjust )
     467             :             {
     468             :                 case SDRTEXTHORZADJUST_RIGHT :
     469             :                 case SDRTEXTHORZADJUST_CENTER:
     470             :                 {
     471           0 :                     std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     472           0 :                     std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     473           0 :                     while ( aParagraphIter != aParagraphIEnd )
     474             :                     {
     475           0 :                         sal_Int32 nHorzDiff = 0;
     476           0 :                         if ( eHorzAdjust == SDRTEXTHORZADJUST_CENTER )
     477           0 :                             nHorzDiff = ( aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() ) / 2;
     478           0 :                         else if ( eHorzAdjust == SDRTEXTHORZADJUST_RIGHT )
     479           0 :                             nHorzDiff = ( aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() );
     480           0 :                         if ( nHorzDiff )
     481             :                         {
     482           0 :                             std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     483           0 :                             std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     484           0 :                             while ( aCharacterIter != aCharacterIEnd )
     485             :                             {
     486           0 :                                 std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     487           0 :                                 std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     488           0 :                                 while( aOutlineIter != aOutlineIEnd )
     489             :                                 {
     490           0 :                                     aOutlineIter->Move( nHorzDiff, 0 );
     491           0 :                                     ++aOutlineIter;
     492             :                                 }
     493           0 :                                 ++aCharacterIter;
     494             :                             }
     495             :                         }
     496           0 :                         ++aParagraphIter;
     497             :                     }
     498             :                 }
     499           0 :                 break;
     500             :                 default:
     501         120 :                 case SDRTEXTHORZADJUST_BLOCK : break;   // don't know
     502           0 :                 case SDRTEXTHORZADJUST_LEFT : break;    // already left aligned -> nothing to do
     503             :             }
     504             :         }
     505         120 :         ++aTextAreaIter;
     506             :     }
     507         108 : }
     508             : 
     509         108 : basegfx::B2DPolyPolygon GetOutlinesFromShape2d( const SdrObject* pShape2d )
     510             : {
     511         108 :     basegfx::B2DPolyPolygon aOutlines2d;
     512             : 
     513         216 :     SdrObjListIter aObjListIter( *pShape2d, IM_DEEPWITHGROUPS );
     514         430 :     while( aObjListIter.IsMore() )
     515             :     {
     516         214 :         SdrObject* pPartObj = aObjListIter.Next();
     517         214 :         if ( pPartObj->ISA( SdrPathObj ) )
     518             :         {
     519         214 :             basegfx::B2DPolyPolygon aCandidate(static_cast<SdrPathObj*>(pPartObj)->GetPathPoly());
     520         214 :             if(aCandidate.areControlPointsUsed())
     521             :             {
     522          56 :                 aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
     523             :             }
     524         214 :             aOutlines2d.append(aCandidate);
     525             :         }
     526             :     }
     527             : 
     528         216 :     return aOutlines2d;
     529             : }
     530             : 
     531         214 : void CalcDistances( const Polygon& rPoly, std::vector< double >& rDistances )
     532             : {
     533         214 :     sal_uInt16 i, nCount = rPoly.GetSize();
     534         214 :     if ( nCount > 1 )
     535             :     {
     536        2884 :         for ( i = 0; i < nCount; i++ )
     537             :         {
     538        2670 :             double fDistance = i ? ((Polygon&)rPoly).CalcDistance( i, i - 1 ) : 0.0;
     539        2670 :             rDistances.push_back( fDistance );
     540             :         }
     541         214 :         std::partial_sum( rDistances.begin(), rDistances.end(), rDistances.begin() );
     542         214 :         double fLength = rDistances[ rDistances.size() - 1 ];
     543         214 :         if ( fLength > 0.0 )
     544             :         {
     545         214 :             std::vector< double >::iterator aIter = rDistances.begin();
     546         214 :             std::vector< double >::iterator aEnd = rDistances.end();
     547        3098 :             while ( aIter != aEnd )
     548        2670 :                 *aIter++ /= fLength;
     549             :         }
     550             :     }
     551         214 : }
     552             : 
     553        3708 : void InsertMissingOutlinePoints( const Polygon& /*rOutlinePoly*/, const std::vector< double >& rDistances, const Rectangle& rTextAreaBoundRect, Polygon& rPoly )
     554             : {
     555        3708 :     sal_uInt16 i = 0;
     556        3708 :     double fLastDistance = 0.0;
     557      350328 :     for ( i = 0; i < rPoly.GetSize(); i++ )
     558             :     {
     559      346620 :         Point& rPoint = rPoly[ i ];
     560      346620 :         double fDistance = (double)( rPoint.X() - rTextAreaBoundRect.Left() ) / (double)rTextAreaBoundRect.GetWidth();
     561      346620 :         if ( i )
     562             :         {
     563      342912 :             if ( fDistance > fLastDistance )
     564             :             {
     565      138334 :                 std::vector< double >::const_iterator aIter = std::upper_bound( rDistances.begin(), rDistances.end(), fLastDistance );
     566      138334 :                 if  ( aIter != rDistances.end() && ( *aIter > fLastDistance ) && ( *aIter < fDistance ) )
     567             :                 {
     568        1442 :                     Point& rPt0 = rPoly[ i - 1 ];
     569        1442 :                     sal_Int32 fX = rPoint.X() - rPt0.X();
     570        1442 :                     sal_Int32 fY = rPoint.Y() - rPt0.Y();
     571        1442 :                     double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
     572        1442 :                     rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
     573        1442 :                     fDistance = *aIter;
     574             :                 }
     575             :             }
     576      204578 :             else if ( fDistance < fLastDistance )
     577             :             {
     578      140752 :                 std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fLastDistance );
     579      140752 :                 if  ( aIter != rDistances.begin() )
     580             :                 {
     581      140752 :                     --aIter;
     582      140752 :                     if ( ( *aIter > fDistance ) && ( *aIter < fLastDistance ) )
     583             :                     {
     584        1442 :                         Point& rPt0 = rPoly[ i - 1 ];
     585        1442 :                         sal_Int32 fX = rPoint.X() - rPt0.X();
     586        1442 :                         sal_Int32 fY = rPoint.Y() - rPt0.Y();
     587        1442 :                         double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
     588        1442 :                         rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
     589        1442 :                         fDistance = *aIter;
     590             :                     }
     591             :                 }
     592             :             }
     593             :         }
     594      346620 :         fLastDistance = fDistance;
     595             :     }
     596        3708 : }
     597             : 
     598      348332 : void GetPoint( const Polygon& rPoly, const std::vector< double >& rDistances, const double& fX, double& fx1, double& fy1 )
     599             : {
     600      348332 :     fy1 = fx1 = 0.0;
     601      348332 :     if ( rPoly.GetSize() > 1 )
     602             :     {
     603      348332 :         std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fX );
     604      348332 :         sal_uInt16 nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
     605      348332 :         if ( aIter == rDistances.end() )
     606           0 :             nIdx--;
     607      348332 :         const Point& rPt = rPoly[ nIdx ];
     608      348332 :         fx1 = rPt.X();
     609      348332 :         fy1 = rPt.Y();
     610      348332 :         if ( nIdx && ( aIter != rDistances.end() ) && ( *aIter != fX ) )
     611             :         {
     612      347886 :             nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
     613      347886 :             double fDist0 = *( aIter - 1 );
     614      347886 :             double fd = ( 1.0 / ( *aIter - fDist0 ) ) * ( fX - fDist0 );
     615      347886 :             const Point& rPt2 = rPoly[ nIdx - 1 ];
     616      347886 :             double fWidth = rPt.X() - rPt2.X();
     617      347886 :             double fHeight= rPt.Y() - rPt2.Y();
     618      347886 :             fWidth *= fd;
     619      347886 :             fHeight*= fd;
     620      347886 :             fx1 = rPt2.X() + fWidth;
     621      347886 :             fy1 = rPt2.Y() + fHeight;
     622             :         }
     623             :     }
     624      348332 : }
     625             : 
     626         108 : void FitTextOutlinesToShapeOutlines( const tools::PolyPolygon& aOutlines2d, FWData& rFWData )
     627             : {
     628         108 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     629         108 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     630             : 
     631         108 :     sal_uInt16 nOutline2dIdx = 0;
     632         336 :     while( aTextAreaIter != aTextAreaIEnd )
     633             :     {
     634         120 :         Rectangle rTextAreaBoundRect = aTextAreaIter->aBoundRect;
     635         120 :         sal_Int32 nLeft = rTextAreaBoundRect.Left();
     636         120 :         sal_Int32 nTop = rTextAreaBoundRect.Top();
     637         120 :         sal_Int32 nWidth = rTextAreaBoundRect.GetWidth();
     638         120 :         sal_Int32 nHeight= rTextAreaBoundRect.GetHeight();
     639         120 :         if ( rFWData.bSingleLineMode && nHeight && nWidth )
     640             :         {
     641          26 :             if ( nOutline2dIdx >= aOutlines2d.Count() )
     642           0 :                 break;
     643          26 :             const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
     644          26 :             const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
     645          26 :             if ( nPointCount > 1 )
     646             :             {
     647          26 :                 std::vector< double > vDistances;
     648          26 :                 vDistances.reserve( nPointCount );
     649          26 :                 CalcDistances( rOutlinePoly, vDistances );
     650          26 :                 if ( !vDistances.empty() )
     651             :                 {
     652          26 :                     std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     653          26 :                     std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     654          78 :                     while( aParagraphIter != aParagraphIEnd )
     655             :                     {
     656          26 :                         std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     657          26 :                         std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     658          78 :                         while ( aCharacterIter != aCharacterIEnd )
     659             :                         {
     660          26 :                             std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     661          26 :                             std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     662         452 :                             while( aOutlineIter != aOutlineIEnd )
     663             :                             {
     664         400 :                                 tools::PolyPolygon& rPolyPoly = *aOutlineIter;
     665         400 :                                 Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
     666         400 :                                 double fx1 = aBoundRect.Left() - nLeft;
     667         400 :                                 double fx2 = aBoundRect.Right() - nLeft;
     668             :                                 double fy1, fy2;
     669         400 :                                 double fM1 = fx1 / (double)nWidth;
     670         400 :                                 double fM2 = fx2 / (double)nWidth;
     671             : 
     672         400 :                                 GetPoint( rOutlinePoly, vDistances, fM1, fx1, fy1 );
     673         400 :                                 GetPoint( rOutlinePoly, vDistances, fM2, fx2, fy2 );
     674             : 
     675         400 :                                 double fvx = ( fy2 - fy1 );
     676         400 :                                 double fvy = - ( fx2 - fx1 );
     677         400 :                                 fx1 = fx1 + ( ( fx2 - fx1 ) * 0.5 );
     678         400 :                                 fy1 = fy1 + ( ( fy2 - fy1 ) * 0.5 );
     679             : 
     680         400 :                                 double fAngle = atan2( -fvx, -fvy );
     681         400 :                                 double fL = hypot( fvx, fvy );
     682         400 :                                 fvx = fvx / fL;
     683         400 :                                 fvy = fvy / fL;
     684         400 :                                 fL = (double)( aTextAreaIter->aBoundRect.GetHeight() / 2.0 + aTextAreaIter->aBoundRect.Top() ) - aParagraphIter->aBoundRect.Center().Y();
     685         400 :                                 fvx *= fL;
     686         400 :                                 fvy *= fL;
     687         400 :                                 rPolyPoly.Rotate( Point( aBoundRect.Center().X(), aParagraphIter->aBoundRect.Center().Y() ), sin( fAngle ), cos( fAngle ) );
     688         400 :                                 rPolyPoly.Move( (sal_Int32)( ( fx1 + fvx )- aBoundRect.Center().X() ), (sal_Int32)( ( fy1 + fvy ) - aParagraphIter->aBoundRect.Center().Y() ) );
     689             : 
     690         400 :                                 ++aOutlineIter;
     691             :                             }
     692          26 :                             ++aCharacterIter;
     693             :                         }
     694          26 :                         ++aParagraphIter;
     695             :                     }
     696          26 :                 }
     697          26 :             }
     698             :         }
     699             :         else
     700             :         {
     701          94 :             if ( ( nOutline2dIdx + 1 ) >= aOutlines2d.Count() )
     702           0 :                 break;
     703          94 :             const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
     704          94 :             const Polygon& rOutlinePoly2( aOutlines2d[ nOutline2dIdx++ ] );
     705          94 :             const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
     706          94 :             const sal_uInt16 nPointCount2 = rOutlinePoly2.GetSize();
     707          94 :             if ( ( nPointCount > 1 ) && ( nPointCount2 > 1 ) )
     708             :             {
     709          94 :                 std::vector< double > vDistances;
     710          94 :                 vDistances.reserve( nPointCount );
     711         188 :                 std::vector< double > vDistances2;
     712          94 :                 vDistances2.reserve( nPointCount2 );
     713          94 :                 CalcDistances( rOutlinePoly, vDistances );
     714          94 :                 CalcDistances( rOutlinePoly2, vDistances2 );
     715          94 :                 std::vector< FWParagraphData >::iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
     716          94 :                 std::vector< FWParagraphData >::iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
     717         314 :                 while( aParagraphIter != aParagraphIEnd )
     718             :                 {
     719         126 :                     std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     720         126 :                     std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     721         374 :                     while ( aCharacterIter != aCharacterIEnd )
     722             :                     {
     723         122 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     724         122 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     725        1496 :                         while( aOutlineIter != aOutlineIEnd )
     726             :                         {
     727        1252 :                             tools::PolyPolygon& rPolyPoly = *aOutlineIter;
     728        1252 :                             sal_uInt16 i, nPolyCount = rPolyPoly.Count();
     729        3106 :                             for ( i = 0; i < nPolyCount; i++ )
     730             :                             {
     731             :                                 // #i35928#
     732        1854 :                                 basegfx::B2DPolygon aCandidate(rPolyPoly[ i ].getB2DPolygon());
     733             : 
     734        1854 :                                 if(aCandidate.areControlPointsUsed())
     735             :                                 {
     736        1564 :                                     aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
     737             :                                 }
     738             : 
     739             :                                 // create local polygon copy to work on
     740        3708 :                                  Polygon aLocalPoly(aCandidate);
     741             : 
     742        1854 :                                 InsertMissingOutlinePoints( rOutlinePoly, vDistances, rTextAreaBoundRect, aLocalPoly );
     743        1854 :                                 InsertMissingOutlinePoints( rOutlinePoly2, vDistances2, rTextAreaBoundRect, aLocalPoly );
     744             : 
     745        1854 :                                 sal_uInt16 _nPointCount = aLocalPoly.GetSize();
     746        1854 :                                 if (_nPointCount)
     747             :                                 {
     748        1854 :                                     if (!nWidth || !nHeight)
     749           0 :                                         throw o3tl::divide_by_zero();
     750      175620 :                                     for (sal_uInt16 j = 0; j < _nPointCount; ++j)
     751             :                                     {
     752      173766 :                                         Point& rPoint = aLocalPoly[ j ];
     753      173766 :                                         rPoint.X() -= nLeft;
     754      173766 :                                         rPoint.Y() -= nTop;
     755      173766 :                                         double fX = (double)rPoint.X() / (double)nWidth;
     756      173766 :                                         double fY = (double)rPoint.Y() / (double)nHeight;
     757             : 
     758             :                                         double fx1, fy1, fx2, fy2;
     759      173766 :                                         GetPoint( rOutlinePoly, vDistances, fX, fx1, fy1 );
     760      173766 :                                         GetPoint( rOutlinePoly2, vDistances2, fX, fx2, fy2 );
     761      173766 :                                         double fWidth = fx2 - fx1;
     762      173766 :                                         double fHeight= fy2 - fy1;
     763      173766 :                                         rPoint.X() = (sal_Int32)( fx1 + fWidth * fY );
     764      173766 :                                         rPoint.Y() = (sal_Int32)( fy1 + fHeight* fY );
     765             :                                     }
     766             :                                 }
     767             : 
     768             :                                 // write back polygon
     769        1854 :                                 rPolyPoly[ i ] = aLocalPoly;
     770        1854 :                             }
     771        1252 :                             ++aOutlineIter;
     772             :                         }
     773         122 :                         ++aCharacterIter;
     774             :                     }
     775         126 :                     ++aParagraphIter;
     776          94 :                 }
     777             :             }
     778             :         }
     779         120 :         ++aTextAreaIter;
     780             :     }
     781         108 : }
     782             : 
     783         108 : SdrObject* CreateSdrObjectFromParagraphOutlines( const FWData& rFWData, const SdrObject* pCustomShape )
     784             : {
     785         108 :     SdrObject* pRet = NULL;
     786         108 :     basegfx::B2DPolyPolygon aPolyPoly;
     787         108 :     if ( !rFWData.vTextAreas.empty() )
     788             :     {
     789         108 :         std::vector< FWTextArea >::const_iterator aTextAreaIter = rFWData.vTextAreas.begin();
     790         108 :         std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     791         336 :         while ( aTextAreaIter != aTextAreaIEnd )
     792             :         {
     793         120 :             std::vector< FWParagraphData >::const_iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
     794         120 :             std::vector< FWParagraphData >::const_iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
     795         392 :             while ( aParagraphIter != aParagraphIEnd )
     796             :             {
     797         152 :                 std::vector< FWCharacterData >::const_iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     798         152 :                 std::vector< FWCharacterData >::const_iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     799         452 :                 while ( aCharacterIter != aCharacterIEnd )
     800             :                 {
     801         148 :                     std::vector< tools::PolyPolygon >::const_iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     802         148 :                     std::vector< tools::PolyPolygon >::const_iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     803        1948 :                     while( aOutlineIter != aOutlineIEnd )
     804             :                     {
     805        1652 :                         aPolyPoly.append( aOutlineIter->getB2DPolyPolygon() );
     806        1652 :                         ++aOutlineIter;
     807             :                     }
     808         148 :                     ++aCharacterIter;
     809             :                 }
     810         152 :                 ++aParagraphIter;
     811             :             }
     812         120 :             ++aTextAreaIter;
     813             :         }
     814             : 
     815         108 :         pRet = new SdrPathObj( OBJ_POLY, aPolyPoly );
     816             : 
     817         108 :         SfxItemSet aSet( pCustomShape->GetMergedItemSet() );
     818         108 :         aSet.ClearItem( SDRATTR_TEXTDIRECTION );    //SJ: vertical writing is not required, by removing this item no outliner is created
     819         108 :         aSet.Put(makeSdrShadowItem(false)); // #i37011# NO shadow for FontWork geometry
     820         108 :         pRet->SetMergedItemSet( aSet );             // * otherwise we would crash, because the outliner tries to create a Paraobject, but there is no model
     821             :     }
     822         108 :     return pRet;
     823             : }
     824             : 
     825         198 : Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::mxBreakIterator = 0;
     826             : 
     827         148 : Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::GetBreakIterator()
     828             : {
     829         148 :     if ( !mxBreakIterator.is() )
     830             :     {
     831          10 :         Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
     832          10 :         mxBreakIterator = i18n::BreakIterator::create(xContext);
     833             :     }
     834         148 :     return mxBreakIterator;
     835             : }
     836             : 
     837         108 : SdrObject* EnhancedCustomShapeFontWork::CreateFontWork( const SdrObject* pShape2d, const SdrObject* pCustomShape )
     838             : {
     839         108 :     SdrObject* pRet = NULL;
     840             : 
     841         108 :     tools::PolyPolygon aOutlines2d( GetOutlinesFromShape2d( pShape2d ) );
     842         108 :     sal_uInt16 nOutlinesCount2d = aOutlines2d.Count();
     843         108 :     if ( nOutlinesCount2d )
     844             :     {
     845         108 :         FWData aFWData;
     846         108 :         if ( InitializeFontWorkData( pCustomShape, nOutlinesCount2d, aFWData ) )
     847             :         {
     848             :             /* retrieves the horizontal scaling factor that has to be used
     849             :             to fit each paragraph text into its corresponding 2d outline */
     850         108 :             CalculateHorizontalScalingFactor( pCustomShape, aFWData, aOutlines2d );
     851             : 
     852             :             /* retrieving the Outlines for the each Paragraph. */
     853             : 
     854         108 :             GetFontWorkOutline( aFWData, pCustomShape );
     855             : 
     856         108 :             FitTextOutlinesToShapeOutlines( aOutlines2d, aFWData );
     857             : 
     858         108 :             pRet = CreateSdrObjectFromParagraphOutlines( aFWData, pCustomShape );
     859         108 :         }
     860             :     }
     861         108 :     return pRet;
     862         594 : }
     863             : 
     864             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10