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