LCOV - code coverage report
Current view: top level - svx/source/customshapes - EnhancedCustomShapeFontWork.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 405 508 79.7 %
Date: 2015-06-13 12:38:46 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         296 : struct FWCharacterData                  // representing a single character
      61             : {
      62             :     std::vector< tools::PolyPolygon >          vOutlines;
      63             :     Rectangle                           aBoundRect;
      64             : };
      65         498 : struct FWParagraphData                  // representing a single paragraph
      66             : {
      67             :     OUString                       aString;
      68             :     std::vector< FWCharacterData >      vCharacters;
      69             :     Rectangle                           aBoundRect;
      70             :     sal_Int16                           nFrameDirection;
      71             : };
      72         258 : struct FWTextArea                       // representing multiple concluding paragraphs
      73             : {
      74             :     std::vector< FWParagraphData >      vParagraphs;
      75             :     Rectangle                           aBoundRect;
      76             : };
      77         108 : 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          54 : static bool InitializeFontWorkData( const SdrObject* pCustomShape, const sal_uInt16 nOutlinesCount2d, FWData& rFWData )
      88             : {
      89          54 :     bool bNoErr = false;
      90          54 :     bool bSingleLineMode = false;
      91          54 :     sal_uInt16 nTextAreaCount = nOutlinesCount2d;
      92          54 :     if ( nOutlinesCount2d & 1 )
      93          13 :         bSingleLineMode = true;
      94             :     else
      95          41 :         nTextAreaCount >>= 1;
      96             : 
      97          54 :     if ( nTextAreaCount )
      98             :     {
      99          54 :         rFWData.bSingleLineMode = bSingleLineMode;
     100             : 
     101             :         // setting the strings
     102          54 :         OutlinerParaObject* pParaObj = static_cast<const SdrObjCustomShape*>(pCustomShape)->GetOutlinerParaObject();
     103          54 :         if ( pParaObj )
     104             :         {
     105          54 :             const EditTextObject& rTextObj = pParaObj->GetTextObject();
     106          54 :             sal_Int32 nParagraphsLeft = rTextObj.GetParagraphCount();
     107             : 
     108          54 :             rFWData.nMaxParagraphsPerTextArea = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
     109          54 :             sal_Int32 j = 0;
     110         168 :             while( nParagraphsLeft && nTextAreaCount )
     111             :             {
     112          60 :                 FWTextArea aTextArea;
     113          60 :                 sal_Int32 i, nParagraphs = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
     114         136 :                 for ( i = 0; i < nParagraphs; ++i, ++j )
     115             :                 {
     116          76 :                     FWParagraphData aParagraphData;
     117          76 :                     aParagraphData.aString = rTextObj.GetText( j );
     118             : 
     119          76 :                     const SfxItemSet& rParaSet = rTextObj.GetParaAttribs( j );  // retrieving some paragraph attributes
     120          76 :                     aParagraphData.nFrameDirection = static_cast<const SvxFrameDirectionItem&>(rParaSet.Get( EE_PARA_WRITINGDIR )).GetValue();
     121          76 :                     aTextArea.vParagraphs.push_back( aParagraphData );
     122          76 :                 }
     123          60 :                 rFWData.vTextAreas.push_back( aTextArea );
     124          60 :                 nParagraphsLeft -= nParagraphs;
     125          60 :                 nTextAreaCount--;
     126          60 :             }
     127          54 :             bNoErr = true;
     128             :         }
     129             :     }
     130          54 :     return bNoErr;
     131             : }
     132             : 
     133         107 : double GetLength( const Polygon& rPolygon )
     134             : {
     135         107 :     double fLength = 0;
     136         107 :     if ( rPolygon.GetSize() > 1 )
     137             :     {
     138         107 :         sal_uInt16 nCount = rPolygon.GetSize();
     139        1442 :         while( --nCount )
     140        1228 :             fLength += ((Polygon&)rPolygon).CalcDistance( nCount, nCount - 1 );
     141             :     }
     142         107 :     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          54 : void CalculateHorizontalScalingFactor( const SdrObject* pCustomShape,
     149             :                                         FWData& rFWData, const tools::PolyPolygon& rOutline2d )
     150             : {
     151          54 :     double fScalingFactor = 1.0;
     152          54 :     bool bScalingFactorDefined = false;
     153             : 
     154          54 :     sal_uInt16 i = 0;
     155          54 :     bool bSingleLineMode = false;
     156          54 :     sal_uInt16 nOutlinesCount2d = rOutline2d.Count();
     157             : 
     158          54 :     vcl::Font aFont;
     159          54 :     const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pCustomShape->GetMergedItem( EE_CHAR_FONTINFO ));
     160          54 :     aFont.SetHeight( pCustomShape->GetLogicRect().GetHeight() / rFWData.nMaxParagraphsPerTextArea );
     161          54 :     aFont.SetAlign( ALIGN_TOP );
     162          54 :     aFont.SetName( rFontItem.GetFamilyName() );
     163          54 :     aFont.SetFamily( rFontItem.GetFamily() );
     164          54 :     aFont.SetStyleName( rFontItem.GetStyleName() );
     165          54 :     aFont.SetOrientation( 0 );
     166             :     // initializing virtual device
     167             : 
     168         108 :     ScopedVclPtrInstance< VirtualDevice > pVirDev( 1 );
     169          54 :     pVirDev->SetMapMode( MAP_100TH_MM );
     170          54 :     pVirDev->SetFont( aFont );
     171             : 
     172          54 :     if ( nOutlinesCount2d & 1 )
     173          13 :         bSingleLineMode = true;
     174             : 
     175          54 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     176          54 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     177         168 :     while( aTextAreaIter != aTextAreaIEnd )
     178             :     {
     179             :         // calculating the width of the corresponding 2d text area
     180          60 :         double fWidth = GetLength( rOutline2d.GetObject( i++ ) );
     181          60 :         if ( !bSingleLineMode )
     182             :         {
     183          47 :             fWidth += GetLength( rOutline2d.GetObject( i++ ) );
     184          47 :             fWidth /= 2.0;
     185             :         }
     186          60 :         std::vector< FWParagraphData >::const_iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     187          60 :         std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     188         196 :         while( aParagraphIter != aParagraphIEnd )
     189             :         {
     190          76 :             double fTextWidth = pVirDev->GetTextWidth( aParagraphIter->aString );
     191          76 :             if ( fTextWidth > 0.0 )
     192             :             {
     193          74 :                 double fScale = fWidth / fTextWidth;
     194          74 :                 if ( !bScalingFactorDefined )
     195             :                 {
     196          54 :                     fScalingFactor = fScale;
     197          54 :                     bScalingFactorDefined = true;
     198             :                 }
     199             :                 else
     200             :                 {
     201          20 :                     if ( fScale < fScalingFactor )
     202          16 :                         fScalingFactor = fScale;
     203             :                 }
     204             :             }
     205          76 :             ++aParagraphIter;
     206             :         }
     207          60 :         ++aTextAreaIter;
     208             :     }
     209         108 :     rFWData.fHorizontalTextScaling = fScalingFactor;
     210          54 : }
     211             : 
     212          60 : void GetTextAreaOutline( const FWData& rFWData, const SdrObject* pCustomShape, FWTextArea& rTextArea, bool bSameLetterHeights )
     213             : {
     214          60 :     bool bIsVertical = static_cast<const SdrObjCustomShape*>(pCustomShape)->IsVerticalWriting();
     215          60 :     sal_Int32 nVerticalOffset = rFWData.nMaxParagraphsPerTextArea > rTextArea.vParagraphs.size()
     216          60 :                                     ? rFWData.nSingleLineHeight / 2 : 0;
     217             : 
     218          60 :     std::vector< FWParagraphData >::iterator aParagraphIter( rTextArea.vParagraphs.begin() );
     219          60 :     std::vector< FWParagraphData >::iterator aParagraphIEnd( rTextArea.vParagraphs.end() );
     220         196 :     while( aParagraphIter != aParagraphIEnd )
     221             :     {
     222          76 :         const OUString& rText = aParagraphIter->aString;
     223          76 :         if ( !rText.isEmpty() )
     224             :         {
     225             :             // generating vcl/font
     226          74 :             sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
     227          74 :             Reference< i18n::XBreakIterator > xBI( EnhancedCustomShapeFontWork::GetBreakIterator() );
     228          74 :             if ( xBI.is() )
     229             :             {
     230          74 :                 nScriptType = xBI->getScriptType( rText, 0 );
     231          74 :                 if( i18n::ScriptType::WEAK == nScriptType )
     232             :                 {
     233           6 :                     sal_Int32 nChg = xBI->endOfScript( rText, 0, nScriptType );
     234           6 :                     if (nChg < rText.getLength() && nChg >= 0)
     235           6 :                         nScriptType = xBI->getScriptType( rText, nChg );
     236             :                     else
     237           0 :                         nScriptType = i18n::ScriptType::LATIN;
     238             :                 }
     239             :             }
     240          74 :             sal_uInt16 nFntItm = EE_CHAR_FONTINFO;
     241          74 :             if ( nScriptType == i18n::ScriptType::COMPLEX )
     242           0 :                 nFntItm = EE_CHAR_FONTINFO_CTL;
     243          74 :             else if ( nScriptType == i18n::ScriptType::ASIAN )
     244           0 :                 nFntItm = EE_CHAR_FONTINFO_CJK;
     245          74 :             const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(pCustomShape->GetMergedItem( nFntItm ));
     246         148 :             vcl::Font aFont;
     247          74 :             aFont.SetHeight( rFWData.nSingleLineHeight );
     248          74 :             aFont.SetAlign( ALIGN_TOP );
     249             : 
     250          74 :             aFont.SetName( rFontItem.GetFamilyName() );
     251          74 :             aFont.SetFamily( rFontItem.GetFamily() );
     252          74 :             aFont.SetStyleName( rFontItem.GetStyleName() );
     253          74 :             aFont.SetOrientation( 0 );
     254             : 
     255          74 :             const SvxPostureItem& rPostureItem = static_cast<const SvxPostureItem&>(pCustomShape->GetMergedItem( EE_CHAR_ITALIC ));
     256          74 :             aFont.SetItalic( rPostureItem.GetPosture() );
     257             : 
     258          74 :             const SvxWeightItem& rWeightItem = static_cast<const SvxWeightItem&>(pCustomShape->GetMergedItem( EE_CHAR_WEIGHT ));
     259          74 :             aFont.SetWeight( rWeightItem.GetWeight() );
     260             : 
     261             :             // initializing virtual device
     262         148 :             ScopedVclPtrInstance< VirtualDevice > pVirDev( 1 );
     263          74 :             pVirDev->SetMapMode( MAP_100TH_MM );
     264          74 :             pVirDev->SetFont( aFont );
     265          74 :             pVirDev->EnableRTL( true );
     266          74 :             if ( aParagraphIter->nFrameDirection == FRMDIR_HORI_RIGHT_TOP )
     267           0 :                 pVirDev->SetLayoutMode( TEXT_LAYOUT_BIDI_RTL );
     268             : 
     269          74 :             const SvxCharScaleWidthItem& rCharScaleWidthItem = static_cast<const SvxCharScaleWidthItem&>(pCustomShape->GetMergedItem( EE_CHAR_FONTWIDTH ));
     270          74 :             sal_uInt16 nCharScaleWidth = rCharScaleWidthItem.GetValue();
     271          74 :             long* pDXArry = NULL;
     272          74 :             sal_Int32 nWidth = 0;
     273             : 
     274             :             // VERTICAL
     275          74 :             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 ( pVirDev->GetTextOutlines( aCharacterData.vOutlines, aCharText, 0, 0, -1, true, nWidth, pDXArry ) )
     286             :                     {
     287           0 :                         sal_Int32 nTextWidth = pVirDev->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          74 :                 if ( ( nCharScaleWidth != 100 ) && nCharScaleWidth )
     335             :                 {   // applying character spacing
     336           0 :                     pDXArry = new long[ rText.getLength() ];
     337           0 :                     pVirDev->GetTextArray( rText, pDXArry);
     338           0 :                     FontMetric aFontMetric( pVirDev->GetFontMetric() );
     339           0 :                     aFont.SetWidth( (sal_Int32)( (double)aFontMetric.GetWidth() * ( (double)100 / (double)nCharScaleWidth ) ) );
     340           0 :                     pVirDev->SetFont( aFont );
     341             :                 }
     342          74 :                 FWCharacterData aCharacterData;
     343          74 :                 if ( pVirDev->GetTextOutlines( aCharacterData.vOutlines, rText, 0, 0, -1, true, nWidth, pDXArry ) )
     344             :                 {
     345          74 :                     aParagraphIter->vCharacters.push_back( aCharacterData );
     346          74 :                 }
     347             :             }
     348          74 :             delete[] pDXArry;
     349             : 
     350             :             // veritcal alignment
     351          74 :             std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     352          74 :             std::vector< FWCharacterData >::iterator aCharacterIEnd ( aParagraphIter->vCharacters.end() );
     353         222 :             while ( aCharacterIter != aCharacterIEnd )
     354             :             {
     355          74 :                 std::vector< tools::PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
     356          74 :                 std::vector< tools::PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
     357         974 :                 while( aOutlineIter != aOutlineIEnd )
     358             :                 {
     359             : 
     360         826 :                     tools::PolyPolygon& rPolyPoly = *aOutlineIter++;
     361             : 
     362         826 :                     if ( nVerticalOffset )
     363         177 :                         rPolyPoly.Move( 0, nVerticalOffset );
     364             : 
     365             :                     // retrieving the boundrect for the paragraph
     366         826 :                     Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
     367         826 :                     aParagraphIter->aBoundRect.Union( aBoundRect );
     368             :                 }
     369          74 :                 ++aCharacterIter;
     370          74 :             }
     371             :         }
     372             :         // updating the boundrect for the text area by merging the current paragraph boundrect
     373          76 :         if ( aParagraphIter->aBoundRect.IsEmpty() )
     374             :         {
     375           2 :             if ( rTextArea.aBoundRect.IsEmpty() )
     376           0 :                 rTextArea.aBoundRect = Rectangle( Point( 0, 0 ), Size( 1, rFWData.nSingleLineHeight ) );
     377             :             else
     378           2 :                 rTextArea.aBoundRect.Bottom() += rFWData.nSingleLineHeight;
     379             :         }
     380             :         else
     381             :         {
     382          74 :             Rectangle& rParagraphBoundRect = aParagraphIter->aBoundRect;
     383          74 :             rTextArea.aBoundRect.Union( rParagraphBoundRect );
     384             : 
     385          74 :             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          76 :         if ( bIsVertical )
     409           0 :             nVerticalOffset -= rFWData.nSingleLineHeight;
     410             :         else
     411          76 :             nVerticalOffset += rFWData.nSingleLineHeight;
     412          76 :         ++aParagraphIter;
     413             :     }
     414          60 : }
     415             : 
     416          54 : void GetFontWorkOutline( FWData& rFWData, const SdrObject* pCustomShape )
     417             : {
     418          54 :     SdrTextHorzAdjust eHorzAdjust( static_cast<const SdrTextHorzAdjustItem&>(pCustomShape->GetMergedItem( SDRATTR_TEXT_HORZADJUST )).GetValue() );
     419          54 :     SdrFitToSizeType  eFTS( static_cast<const SdrTextFitToSizeTypeItem&>(pCustomShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
     420             : 
     421          54 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     422          54 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     423             : 
     424          54 :     rFWData.nSingleLineHeight = (sal_Int32)( ( (double)pCustomShape->GetLogicRect().GetHeight()
     425          54 :                                                 / rFWData.nMaxParagraphsPerTextArea ) * rFWData.fHorizontalTextScaling );
     426             : 
     427          54 :     bool bSameLetterHeights = false;
     428          54 :     const SdrCustomShapeGeometryItem& rGeometryItem = static_cast<const SdrCustomShapeGeometryItem&>(pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
     429          54 :     const com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "SameLetterHeights" );
     430          54 :     if ( pAny )
     431          54 :         *pAny >>= bSameLetterHeights;
     432             : 
     433         168 :     while ( aTextAreaIter != aTextAreaIEnd )
     434             :     {
     435          60 :         GetTextAreaOutline( rFWData, pCustomShape, *aTextAreaIter, bSameLetterHeights );
     436          60 :         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          60 :             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          60 :                 case SDRTEXTHORZADJUST_BLOCK : break;   // don't know
     502           0 :                 case SDRTEXTHORZADJUST_LEFT : break;    // already left aligned -> nothing to do
     503             :             }
     504             :         }
     505          60 :         ++aTextAreaIter;
     506             :     }
     507          54 : }
     508             : 
     509          54 : basegfx::B2DPolyPolygon GetOutlinesFromShape2d( const SdrObject* pShape2d )
     510             : {
     511          54 :     basegfx::B2DPolyPolygon aOutlines2d;
     512             : 
     513         108 :     SdrObjListIter aObjListIter( *pShape2d, IM_DEEPWITHGROUPS );
     514         215 :     while( aObjListIter.IsMore() )
     515             :     {
     516         107 :         SdrObject* pPartObj = aObjListIter.Next();
     517         107 :         if ( pPartObj->ISA( SdrPathObj ) )
     518             :         {
     519         107 :             basegfx::B2DPolyPolygon aCandidate(static_cast<SdrPathObj*>(pPartObj)->GetPathPoly());
     520         107 :             if(aCandidate.areControlPointsUsed())
     521             :             {
     522          28 :                 aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
     523             :             }
     524         107 :             aOutlines2d.append(aCandidate);
     525             :         }
     526             :     }
     527             : 
     528         108 :     return aOutlines2d;
     529             : }
     530             : 
     531         107 : void CalcDistances( const Polygon& rPoly, std::vector< double >& rDistances )
     532             : {
     533         107 :     sal_uInt16 i, nCount = rPoly.GetSize();
     534         107 :     if ( nCount > 1 )
     535             :     {
     536        1442 :         for ( i = 0; i < nCount; i++ )
     537             :         {
     538        1335 :             double fDistance = i ? ((Polygon&)rPoly).CalcDistance( i, i - 1 ) : 0.0;
     539        1335 :             rDistances.push_back( fDistance );
     540             :         }
     541         107 :         std::partial_sum( rDistances.begin(), rDistances.end(), rDistances.begin() );
     542         107 :         double fLength = rDistances[ rDistances.size() - 1 ];
     543         107 :         if ( fLength > 0.0 )
     544             :         {
     545         107 :             std::vector< double >::iterator aIter = rDistances.begin();
     546         107 :             std::vector< double >::iterator aEnd = rDistances.end();
     547        1549 :             while ( aIter != aEnd )
     548        1335 :                 *aIter++ /= fLength;
     549             :         }
     550             :     }
     551         107 : }
     552             : 
     553        1854 : void InsertMissingOutlinePoints( const Polygon& /*rOutlinePoly*/, const std::vector< double >& rDistances, const Rectangle& rTextAreaBoundRect, Polygon& rPoly )
     554             : {
     555        1854 :     sal_uInt16 nSize = rPoly.GetSize();
     556        1854 :     if (nSize == 0)
     557        1854 :         return;
     558             : 
     559        1854 :     long nTextWidth = rTextAreaBoundRect.GetWidth();
     560             : 
     561        1854 :     if (nTextWidth == 0)
     562           0 :         throw o3tl::divide_by_zero();
     563             : 
     564        1854 :     double fLastDistance = 0.0;
     565      173671 :     for (sal_uInt16 i = 0; i < nSize; ++i)
     566             :     {
     567      171817 :         Point& rPoint = rPoly[ i ];
     568      171817 :         double fDistance = (double)( rPoint.X() - rTextAreaBoundRect.Left() ) / (double)nTextWidth;
     569      171817 :         if ( i )
     570             :         {
     571      169963 :             if ( fDistance > fLastDistance )
     572             :             {
     573       68393 :                 std::vector< double >::const_iterator aIter = std::upper_bound( rDistances.begin(), rDistances.end(), fLastDistance );
     574       68393 :                 if  ( aIter != rDistances.end() && ( *aIter > fLastDistance ) && ( *aIter < fDistance ) )
     575             :                 {
     576         661 :                     Point& rPt0 = rPoly[ i - 1 ];
     577         661 :                     sal_Int32 fX = rPoint.X() - rPt0.X();
     578         661 :                     sal_Int32 fY = rPoint.Y() - rPt0.Y();
     579         661 :                     double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
     580         661 :                     rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
     581         661 :                     fDistance = *aIter;
     582             :                 }
     583             :             }
     584      101570 :             else if ( fDistance < fLastDistance )
     585             :             {
     586       69976 :                 std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fLastDistance );
     587       69976 :                 if  ( aIter != rDistances.begin() )
     588             :                 {
     589       69976 :                     --aIter;
     590       69976 :                     if ( ( *aIter > fDistance ) && ( *aIter < fLastDistance ) )
     591             :                     {
     592         655 :                         Point& rPt0 = rPoly[ i - 1 ];
     593         655 :                         sal_Int32 fX = rPoint.X() - rPt0.X();
     594         655 :                         sal_Int32 fY = rPoint.Y() - rPt0.Y();
     595         655 :                         double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
     596         655 :                         rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
     597         655 :                         fDistance = *aIter;
     598             :                     }
     599             :                 }
     600             :             }
     601             :         }
     602      171817 :         fLastDistance = fDistance;
     603             :     }
     604             : }
     605             : 
     606      173936 : void GetPoint( const Polygon& rPoly, const std::vector< double >& rDistances, const double& fX, double& fx1, double& fy1 )
     607             : {
     608      173936 :     fy1 = fx1 = 0.0;
     609      173936 :     if ( rPoly.GetSize() > 1 )
     610             :     {
     611      173936 :         std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fX );
     612      173936 :         sal_uInt16 nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
     613      173936 :         if ( aIter == rDistances.end() )
     614           0 :             nIdx--;
     615      173936 :         const Point& rPt = rPoly[ nIdx ];
     616      173936 :         fx1 = rPt.X();
     617      173936 :         fy1 = rPt.Y();
     618      173936 :         if ( nIdx && ( aIter != rDistances.end() ) && ( *aIter != fX ) )
     619             :         {
     620      173713 :             nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
     621      173713 :             double fDist0 = *( aIter - 1 );
     622      173713 :             double fd = ( 1.0 / ( *aIter - fDist0 ) ) * ( fX - fDist0 );
     623      173713 :             const Point& rPt2 = rPoly[ nIdx - 1 ];
     624      173713 :             double fWidth = rPt.X() - rPt2.X();
     625      173713 :             double fHeight= rPt.Y() - rPt2.Y();
     626      173713 :             fWidth *= fd;
     627      173713 :             fHeight*= fd;
     628      173713 :             fx1 = rPt2.X() + fWidth;
     629      173713 :             fy1 = rPt2.Y() + fHeight;
     630             :         }
     631             :     }
     632      173936 : }
     633             : 
     634          54 : void FitTextOutlinesToShapeOutlines( const tools::PolyPolygon& aOutlines2d, FWData& rFWData )
     635             : {
     636          54 :     std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
     637          54 :     std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     638             : 
     639          54 :     sal_uInt16 nOutline2dIdx = 0;
     640         168 :     while( aTextAreaIter != aTextAreaIEnd )
     641             :     {
     642          60 :         Rectangle rTextAreaBoundRect = aTextAreaIter->aBoundRect;
     643          60 :         sal_Int32 nLeft = rTextAreaBoundRect.Left();
     644          60 :         sal_Int32 nTop = rTextAreaBoundRect.Top();
     645          60 :         sal_Int32 nWidth = rTextAreaBoundRect.GetWidth();
     646          60 :         sal_Int32 nHeight= rTextAreaBoundRect.GetHeight();
     647          60 :         if ( rFWData.bSingleLineMode && nHeight && nWidth )
     648             :         {
     649          13 :             if ( nOutline2dIdx >= aOutlines2d.Count() )
     650           0 :                 break;
     651          13 :             const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
     652          13 :             const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
     653          13 :             if ( nPointCount > 1 )
     654             :             {
     655          13 :                 std::vector< double > vDistances;
     656          13 :                 vDistances.reserve( nPointCount );
     657          13 :                 CalcDistances( rOutlinePoly, vDistances );
     658          13 :                 if ( !vDistances.empty() )
     659             :                 {
     660          13 :                     std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
     661          13 :                     std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
     662          39 :                     while( aParagraphIter != aParagraphIEnd )
     663             :                     {
     664          13 :                         std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     665          13 :                         std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     666          39 :                         while ( aCharacterIter != aCharacterIEnd )
     667             :                         {
     668          13 :                             std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     669          13 :                             std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     670         226 :                             while( aOutlineIter != aOutlineIEnd )
     671             :                             {
     672         200 :                                 tools::PolyPolygon& rPolyPoly = *aOutlineIter;
     673         200 :                                 Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
     674         200 :                                 double fx1 = aBoundRect.Left() - nLeft;
     675         200 :                                 double fx2 = aBoundRect.Right() - nLeft;
     676             :                                 double fy1, fy2;
     677         200 :                                 double fM1 = fx1 / (double)nWidth;
     678         200 :                                 double fM2 = fx2 / (double)nWidth;
     679             : 
     680         200 :                                 GetPoint( rOutlinePoly, vDistances, fM1, fx1, fy1 );
     681         200 :                                 GetPoint( rOutlinePoly, vDistances, fM2, fx2, fy2 );
     682             : 
     683         200 :                                 double fvx = ( fy2 - fy1 );
     684         200 :                                 double fvy = - ( fx2 - fx1 );
     685         200 :                                 fx1 = fx1 + ( ( fx2 - fx1 ) * 0.5 );
     686         200 :                                 fy1 = fy1 + ( ( fy2 - fy1 ) * 0.5 );
     687             : 
     688         200 :                                 double fAngle = atan2( -fvx, -fvy );
     689         200 :                                 double fL = hypot( fvx, fvy );
     690         200 :                                 fvx = fvx / fL;
     691         200 :                                 fvy = fvy / fL;
     692         200 :                                 fL = (double)( aTextAreaIter->aBoundRect.GetHeight() / 2.0 + aTextAreaIter->aBoundRect.Top() ) - aParagraphIter->aBoundRect.Center().Y();
     693         200 :                                 fvx *= fL;
     694         200 :                                 fvy *= fL;
     695         200 :                                 rPolyPoly.Rotate( Point( aBoundRect.Center().X(), aParagraphIter->aBoundRect.Center().Y() ), sin( fAngle ), cos( fAngle ) );
     696         200 :                                 rPolyPoly.Move( (sal_Int32)( ( fx1 + fvx )- aBoundRect.Center().X() ), (sal_Int32)( ( fy1 + fvy ) - aParagraphIter->aBoundRect.Center().Y() ) );
     697             : 
     698         200 :                                 ++aOutlineIter;
     699             :                             }
     700          13 :                             ++aCharacterIter;
     701             :                         }
     702          13 :                         ++aParagraphIter;
     703             :                     }
     704          13 :                 }
     705          13 :             }
     706             :         }
     707             :         else
     708             :         {
     709          47 :             if ( ( nOutline2dIdx + 1 ) >= aOutlines2d.Count() )
     710           0 :                 break;
     711          47 :             const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
     712          47 :             const Polygon& rOutlinePoly2( aOutlines2d[ nOutline2dIdx++ ] );
     713          47 :             const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
     714          47 :             const sal_uInt16 nPointCount2 = rOutlinePoly2.GetSize();
     715          47 :             if ( ( nPointCount > 1 ) && ( nPointCount2 > 1 ) )
     716             :             {
     717          47 :                 std::vector< double > vDistances;
     718          47 :                 vDistances.reserve( nPointCount );
     719          94 :                 std::vector< double > vDistances2;
     720          47 :                 vDistances2.reserve( nPointCount2 );
     721          47 :                 CalcDistances( rOutlinePoly, vDistances );
     722          47 :                 CalcDistances( rOutlinePoly2, vDistances2 );
     723          47 :                 std::vector< FWParagraphData >::iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
     724          47 :                 std::vector< FWParagraphData >::iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
     725         157 :                 while( aParagraphIter != aParagraphIEnd )
     726             :                 {
     727          63 :                     std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     728          63 :                     std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     729         187 :                     while ( aCharacterIter != aCharacterIEnd )
     730             :                     {
     731          61 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     732          61 :                         std::vector< tools::PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     733         748 :                         while( aOutlineIter != aOutlineIEnd )
     734             :                         {
     735         626 :                             tools::PolyPolygon& rPolyPoly = *aOutlineIter;
     736         626 :                             sal_uInt16 i, nPolyCount = rPolyPoly.Count();
     737        1553 :                             for ( i = 0; i < nPolyCount; i++ )
     738             :                             {
     739             :                                 // #i35928#
     740         927 :                                 basegfx::B2DPolygon aCandidate(rPolyPoly[ i ].getB2DPolygon());
     741             : 
     742         927 :                                 if(aCandidate.areControlPointsUsed())
     743             :                                 {
     744         782 :                                     aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
     745             :                                 }
     746             : 
     747             :                                 // create local polygon copy to work on
     748        1854 :                                  Polygon aLocalPoly(aCandidate);
     749             : 
     750         927 :                                 InsertMissingOutlinePoints( rOutlinePoly, vDistances, rTextAreaBoundRect, aLocalPoly );
     751         927 :                                 InsertMissingOutlinePoints( rOutlinePoly2, vDistances2, rTextAreaBoundRect, aLocalPoly );
     752             : 
     753         927 :                                 sal_uInt16 _nPointCount = aLocalPoly.GetSize();
     754         927 :                                 if (_nPointCount)
     755             :                                 {
     756         927 :                                     if (!nWidth || !nHeight)
     757           0 :                                         throw o3tl::divide_by_zero();
     758       87695 :                                     for (sal_uInt16 j = 0; j < _nPointCount; ++j)
     759             :                                     {
     760       86768 :                                         Point& rPoint = aLocalPoly[ j ];
     761       86768 :                                         rPoint.X() -= nLeft;
     762       86768 :                                         rPoint.Y() -= nTop;
     763       86768 :                                         double fX = (double)rPoint.X() / (double)nWidth;
     764       86768 :                                         double fY = (double)rPoint.Y() / (double)nHeight;
     765             : 
     766             :                                         double fx1, fy1, fx2, fy2;
     767       86768 :                                         GetPoint( rOutlinePoly, vDistances, fX, fx1, fy1 );
     768       86768 :                                         GetPoint( rOutlinePoly2, vDistances2, fX, fx2, fy2 );
     769       86768 :                                         double fWidth = fx2 - fx1;
     770       86768 :                                         double fHeight= fy2 - fy1;
     771       86768 :                                         rPoint.X() = (sal_Int32)( fx1 + fWidth * fY );
     772       86768 :                                         rPoint.Y() = (sal_Int32)( fy1 + fHeight* fY );
     773             :                                     }
     774             :                                 }
     775             : 
     776             :                                 // write back polygon
     777         927 :                                 rPolyPoly[ i ] = aLocalPoly;
     778         927 :                             }
     779         626 :                             ++aOutlineIter;
     780             :                         }
     781          61 :                         ++aCharacterIter;
     782             :                     }
     783          63 :                     ++aParagraphIter;
     784          47 :                 }
     785             :             }
     786             :         }
     787          60 :         ++aTextAreaIter;
     788             :     }
     789          54 : }
     790             : 
     791          54 : SdrObject* CreateSdrObjectFromParagraphOutlines( const FWData& rFWData, const SdrObject* pCustomShape )
     792             : {
     793          54 :     SdrObject* pRet = NULL;
     794          54 :     basegfx::B2DPolyPolygon aPolyPoly;
     795          54 :     if ( !rFWData.vTextAreas.empty() )
     796             :     {
     797          54 :         std::vector< FWTextArea >::const_iterator aTextAreaIter = rFWData.vTextAreas.begin();
     798          54 :         std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end();
     799         168 :         while ( aTextAreaIter != aTextAreaIEnd )
     800             :         {
     801          60 :             std::vector< FWParagraphData >::const_iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
     802          60 :             std::vector< FWParagraphData >::const_iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
     803         196 :             while ( aParagraphIter != aParagraphIEnd )
     804             :             {
     805          76 :                 std::vector< FWCharacterData >::const_iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
     806          76 :                 std::vector< FWCharacterData >::const_iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
     807         226 :                 while ( aCharacterIter != aCharacterIEnd )
     808             :                 {
     809          74 :                     std::vector< tools::PolyPolygon >::const_iterator aOutlineIter = aCharacterIter->vOutlines.begin();
     810          74 :                     std::vector< tools::PolyPolygon >::const_iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
     811         974 :                     while( aOutlineIter != aOutlineIEnd )
     812             :                     {
     813         826 :                         aPolyPoly.append( aOutlineIter->getB2DPolyPolygon() );
     814         826 :                         ++aOutlineIter;
     815             :                     }
     816          74 :                     ++aCharacterIter;
     817             :                 }
     818          76 :                 ++aParagraphIter;
     819             :             }
     820          60 :             ++aTextAreaIter;
     821             :         }
     822             : 
     823          54 :         pRet = new SdrPathObj( OBJ_POLY, aPolyPoly );
     824             : 
     825          54 :         SfxItemSet aSet( pCustomShape->GetMergedItemSet() );
     826          54 :         aSet.ClearItem( SDRATTR_TEXTDIRECTION );    //SJ: vertical writing is not required, by removing this item no outliner is created
     827          54 :         aSet.Put(makeSdrShadowItem(false)); // #i37011# NO shadow for FontWork geometry
     828          54 :         pRet->SetMergedItemSet( aSet );             // * otherwise we would crash, because the outliner tries to create a Paraobject, but there is no model
     829             :     }
     830          54 :     return pRet;
     831             : }
     832             : 
     833         130 : Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::mxBreakIterator = 0;
     834             : 
     835          74 : Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::GetBreakIterator()
     836             : {
     837          74 :     if ( !mxBreakIterator.is() )
     838             :     {
     839           6 :         Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
     840           6 :         mxBreakIterator = i18n::BreakIterator::create(xContext);
     841             :     }
     842          74 :     return mxBreakIterator;
     843             : }
     844             : 
     845          54 : SdrObject* EnhancedCustomShapeFontWork::CreateFontWork( const SdrObject* pShape2d, const SdrObject* pCustomShape )
     846             : {
     847          54 :     SdrObject* pRet = NULL;
     848             : 
     849          54 :     tools::PolyPolygon aOutlines2d( GetOutlinesFromShape2d( pShape2d ) );
     850          54 :     sal_uInt16 nOutlinesCount2d = aOutlines2d.Count();
     851          54 :     if ( nOutlinesCount2d )
     852             :     {
     853          54 :         FWData aFWData;
     854          54 :         if ( InitializeFontWorkData( pCustomShape, nOutlinesCount2d, aFWData ) )
     855             :         {
     856             :             /* retrieves the horizontal scaling factor that has to be used
     857             :             to fit each paragraph text into its corresponding 2d outline */
     858          54 :             CalculateHorizontalScalingFactor( pCustomShape, aFWData, aOutlines2d );
     859             : 
     860             :             /* retrieving the Outlines for the each Paragraph. */
     861             : 
     862          54 :             GetFontWorkOutline( aFWData, pCustomShape );
     863             : 
     864          54 :             FitTextOutlinesToShapeOutlines( aOutlines2d, aFWData );
     865             : 
     866          54 :             pRet = CreateSdrObjectFromParagraphOutlines( aFWData, pCustomShape );
     867          54 :         }
     868             :     }
     869          54 :     return pRet;
     870         390 : }
     871             : 
     872             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11