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
10f6e50924SAndrew Rist *
11f6e50924SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12f6e50924SAndrew Rist *
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.
19f6e50924SAndrew Rist *
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();
118cdf0e10cSrcweir sal_Int32 nParagraphsLeft = rTextObj.GetParagraphCount();
119cdf0e10cSrcweir
120cdf0e10cSrcweir rFWData.nMaxParagraphsPerTextArea = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
121cdf0e10cSrcweir sal_Int16 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
383cdf0e10cSrcweir // veritcal 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() );
452*26734c99SArmin 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 );
471*26734c99SArmin 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