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