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