1*f6e50924SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*f6e50924SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*f6e50924SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*f6e50924SAndrew Rist * distributed with this work for additional information 6*f6e50924SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*f6e50924SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*f6e50924SAndrew Rist * "License"); you may not use this file except in compliance 9*f6e50924SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*f6e50924SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*f6e50924SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*f6e50924SAndrew Rist * software distributed under the License is distributed on an 15*f6e50924SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*f6e50924SAndrew Rist * KIND, either express or implied. See the License for the 17*f6e50924SAndrew Rist * specific language governing permissions and limitations 18*f6e50924SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*f6e50924SAndrew Rist *************************************************************/ 21*f6e50924SAndrew Rist 22*f6e50924SAndrew 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 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 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 */ 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 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 449cdf0e10cSrcweir void GetFontWorkOutline( FWData& rFWData, const SdrObject* pCustomShape ) 450cdf0e10cSrcweir { 451cdf0e10cSrcweir SdrTextHorzAdjust eHorzAdjust( ((SdrTextHorzAdjustItem&)pCustomShape->GetMergedItem( SDRATTR_TEXT_HORZADJUST )).GetValue() ); 452cdf0e10cSrcweir 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 ); 471cdf0e10cSrcweir 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 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 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 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 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 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 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 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 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