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