2010-10-12 15:53:47 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-11-21 22:06:52 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*
|
|
|
|
* This file incorporates work covered by the following license notice:
|
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
|
|
* with this work for additional information regarding copyright
|
|
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
|
|
*/
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
#include "EnhancedCustomShapeFontWork.hxx"
|
|
|
|
#include <tools/solar.h> // UINTXX
|
2007-06-27 15:43:58 +00:00
|
|
|
#include <svx/svddef.hxx>
|
|
|
|
#include <svx/svdogrp.hxx>
|
|
|
|
#include <svx/svdopath.hxx>
|
2004-04-02 13:03:55 +00:00
|
|
|
#include <vcl/metric.hxx>
|
2007-06-27 15:43:58 +00:00
|
|
|
#include <svx/svdpage.hxx>
|
|
|
|
#include <svx/sdasitm.hxx>
|
|
|
|
#include <svx/sdasaitm.hxx>
|
|
|
|
#include <svx/sdtfsitm.hxx>
|
2004-04-02 13:03:55 +00:00
|
|
|
#include <vcl/virdev.hxx>
|
2010-04-20 15:55:51 +02:00
|
|
|
#include <svx/svditer.hxx>
|
2010-01-07 18:52:36 +01:00
|
|
|
#include <editeng/eeitem.hxx>
|
|
|
|
#include <editeng/frmdiritem.hxx>
|
|
|
|
#include <editeng/fontitem.hxx>
|
|
|
|
#include <editeng/postitem.hxx>
|
|
|
|
#include <editeng/wghtitem.hxx>
|
|
|
|
#include <editeng/charscaleitem.hxx>
|
2010-04-20 15:55:51 +02:00
|
|
|
#include "svx/EnhancedCustomShapeTypeNames.hxx"
|
2007-06-27 15:43:58 +00:00
|
|
|
#include <svx/svdorect.hxx>
|
|
|
|
#include <svx/svdoashp.hxx>
|
2010-01-07 18:52:36 +01:00
|
|
|
#include <editeng/outliner.hxx>
|
|
|
|
#include <editeng/outlobj.hxx>
|
|
|
|
#include <editeng/editobj.hxx>
|
|
|
|
#include <editeng/editeng.hxx>
|
2007-06-27 15:43:58 +00:00
|
|
|
#include <svx/svdmodel.hxx>
|
2004-04-02 13:03:55 +00:00
|
|
|
#include <vector>
|
|
|
|
#include <numeric>
|
|
|
|
#include <algorithm>
|
2005-02-21 15:17:39 +00:00
|
|
|
#include <comphelper/processfactory.hxx>
|
2012-10-15 15:20:48 +02:00
|
|
|
#include <com/sun/star/i18n/BreakIterator.hpp>
|
2012-06-21 17:39:01 +01:00
|
|
|
#include <com/sun/star/i18n/ScriptType.hpp>
|
2004-11-03 09:34:18 +00:00
|
|
|
#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
2005-02-21 15:17:39 +00:00
|
|
|
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
|
2012-06-21 17:39:01 +01:00
|
|
|
#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
|
2004-11-03 09:34:18 +00:00
|
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
|
|
|
2005-02-21 15:17:39 +00:00
|
|
|
using namespace com::sun::star;
|
2004-04-02 13:03:55 +00:00
|
|
|
using namespace com::sun::star::uno;
|
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
struct FWCharacterData // representing a single character
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
std::vector< PolyPolygon > vOutlines;
|
|
|
|
Rectangle aBoundRect;
|
|
|
|
};
|
2004-10-12 13:12:01 +00:00
|
|
|
struct FWParagraphData // representing a single paragraph
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
rtl::OUString aString;
|
|
|
|
std::vector< FWCharacterData > vCharacters;
|
2004-04-02 13:03:55 +00:00
|
|
|
Rectangle aBoundRect;
|
2005-02-21 15:17:39 +00:00
|
|
|
sal_Int16 nFrameDirection;
|
2004-04-02 13:03:55 +00:00
|
|
|
};
|
2004-10-12 13:12:01 +00:00
|
|
|
struct FWTextArea // representing multiple concluding paragraphs
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData > vParagraphs;
|
|
|
|
Rectangle aBoundRect;
|
|
|
|
};
|
|
|
|
struct FWData // representing the whole text
|
|
|
|
{
|
|
|
|
std::vector< FWTextArea > vTextAreas;
|
2004-04-02 13:03:55 +00:00
|
|
|
double fHorizontalTextScaling;
|
|
|
|
sal_uInt32 nMaxParagraphsPerTextArea;
|
|
|
|
sal_Int32 nSingleLineHeight;
|
2013-03-15 10:56:55 +09:00
|
|
|
bool bSingleLineMode;
|
2004-04-02 13:03:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-03-15 10:56:55 +09:00
|
|
|
static bool InitializeFontWorkData( const SdrObject* pCustomShape, const sal_uInt16 nOutlinesCount2d, FWData& rFWData )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2013-03-15 10:56:55 +09:00
|
|
|
bool bNoErr = false;
|
|
|
|
bool bSingleLineMode = false;
|
2004-04-02 13:03:55 +00:00
|
|
|
sal_uInt16 nTextAreaCount = nOutlinesCount2d;
|
|
|
|
if ( nOutlinesCount2d & 1 )
|
2013-03-15 10:56:55 +09:00
|
|
|
bSingleLineMode = true;
|
2004-04-02 13:03:55 +00:00
|
|
|
else
|
|
|
|
nTextAreaCount >>= 1;
|
|
|
|
|
|
|
|
if ( nTextAreaCount )
|
|
|
|
{
|
|
|
|
rFWData.bSingleLineMode = bSingleLineMode;
|
|
|
|
|
|
|
|
// setting the strings
|
|
|
|
OutlinerParaObject* pParaObj = ((SdrObjCustomShape*)pCustomShape)->GetOutlinerParaObject();
|
|
|
|
if ( pParaObj )
|
|
|
|
{
|
|
|
|
const EditTextObject& rTextObj = pParaObj->GetTextObject();
|
2006-10-12 11:02:19 +00:00
|
|
|
sal_Int32 nParagraphsLeft = rTextObj.GetParagraphCount();
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
rFWData.nMaxParagraphsPerTextArea = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
|
2005-09-23 12:49:43 +00:00
|
|
|
sal_Int16 j = 0;
|
2004-04-02 13:03:55 +00:00
|
|
|
while( nParagraphsLeft && nTextAreaCount )
|
|
|
|
{
|
|
|
|
FWTextArea aTextArea;
|
2006-10-12 11:02:19 +00:00
|
|
|
sal_Int32 i, nParagraphs = ( ( nParagraphsLeft - 1 ) / nTextAreaCount ) + 1;
|
2010-12-29 09:52:22 +01:00
|
|
|
for ( i = 0; i < nParagraphs; ++i, ++j )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
FWParagraphData aParagraphData;
|
2005-09-23 12:49:43 +00:00
|
|
|
aParagraphData.aString = rTextObj.GetText( j );
|
2005-02-21 15:17:39 +00:00
|
|
|
|
2005-09-23 12:49:43 +00:00
|
|
|
const SfxItemSet& rParaSet = rTextObj.GetParaAttribs( j ); // retrieving some paragraph attributes
|
2005-02-21 15:17:39 +00:00
|
|
|
aParagraphData.nFrameDirection = ((SvxFrameDirectionItem&)rParaSet.Get( EE_PARA_WRITINGDIR )).GetValue();
|
2004-10-12 13:12:01 +00:00
|
|
|
aTextArea.vParagraphs.push_back( aParagraphData );
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2004-10-12 13:12:01 +00:00
|
|
|
rFWData.vTextAreas.push_back( aTextArea );
|
2004-04-02 13:03:55 +00:00
|
|
|
nParagraphsLeft -= nParagraphs;
|
|
|
|
nTextAreaCount--;
|
|
|
|
}
|
2013-03-15 10:56:55 +09:00
|
|
|
bNoErr = true;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return bNoErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
double GetLength( const Polygon& rPolygon )
|
|
|
|
{
|
|
|
|
double fLength = 0;
|
|
|
|
if ( rPolygon.GetSize() > 1 )
|
|
|
|
{
|
|
|
|
sal_uInt16 nCount = rPolygon.GetSize();
|
|
|
|
while( --nCount )
|
|
|
|
fLength += ((Polygon&)rPolygon).CalcDistance( nCount, nCount - 1 );
|
|
|
|
}
|
|
|
|
return fLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* CalculateHorizontalScalingFactor returns the horizontal scaling factor for
|
|
|
|
the whole text object, so that each text will match its corresponding 2d Outline */
|
|
|
|
void CalculateHorizontalScalingFactor( const SdrObject* pCustomShape,
|
|
|
|
FWData& rFWData, const PolyPolygon& rOutline2d )
|
|
|
|
{
|
|
|
|
double fScalingFactor = 1.0;
|
2013-03-15 10:56:55 +09:00
|
|
|
bool bScalingFactorDefined = false;
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
sal_uInt16 i = 0;
|
2013-03-15 10:56:55 +09:00
|
|
|
bool bSingleLineMode = false;
|
2004-04-02 13:03:55 +00:00
|
|
|
sal_uInt16 nOutlinesCount2d = rOutline2d.Count();
|
|
|
|
|
|
|
|
Font aFont;
|
|
|
|
SvxFontItem& rFontItem = (SvxFontItem&)pCustomShape->GetMergedItem( EE_CHAR_FONTINFO );
|
|
|
|
aFont.SetHeight( pCustomShape->GetLogicRect().GetHeight() / rFWData.nMaxParagraphsPerTextArea );
|
|
|
|
aFont.SetAlign( ALIGN_TOP );
|
|
|
|
aFont.SetName( rFontItem.GetFamilyName() );
|
|
|
|
aFont.SetFamily( rFontItem.GetFamily() );
|
|
|
|
aFont.SetStyleName( rFontItem.GetStyleName() );
|
|
|
|
aFont.SetOrientation( 0 );
|
|
|
|
// initializing virtual device
|
|
|
|
|
|
|
|
VirtualDevice aVirDev( 1 );
|
|
|
|
aVirDev.SetMapMode( MAP_100TH_MM );
|
|
|
|
aVirDev.SetFont( aFont );
|
|
|
|
|
|
|
|
if ( nOutlinesCount2d & 1 )
|
2013-03-15 10:56:55 +09:00
|
|
|
bSingleLineMode = true;
|
2004-04-02 13:03:55 +00:00
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
|
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
|
|
|
|
while( aTextAreaIter != aTextAreaIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
// calculating the width of the corresponding 2d text area
|
|
|
|
double fWidth = GetLength( rOutline2d.GetObject( i++ ) );
|
|
|
|
if ( !bSingleLineMode )
|
|
|
|
{
|
|
|
|
fWidth += GetLength( rOutline2d.GetObject( i++ ) );
|
|
|
|
fWidth /= 2.0;
|
|
|
|
}
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::const_iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
|
|
|
|
std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
|
|
|
|
while( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
double fTextWidth = aVirDev.GetTextWidth( aParagraphIter->aString );
|
2004-04-02 13:03:55 +00:00
|
|
|
if ( fTextWidth > 0.0 )
|
|
|
|
{
|
|
|
|
double fScale = fWidth / fTextWidth;
|
|
|
|
if ( !bScalingFactorDefined )
|
|
|
|
{
|
|
|
|
fScalingFactor = fScale;
|
2013-03-15 10:56:55 +09:00
|
|
|
bScalingFactorDefined = true;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( fScale < fScalingFactor )
|
|
|
|
fScalingFactor = fScale;
|
|
|
|
}
|
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aTextAreaIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
rFWData.fHorizontalTextScaling = fScalingFactor;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetTextAreaOutline( const FWData& rFWData, const SdrObject* pCustomShape, FWTextArea& rTextArea, sal_Bool bSameLetterHeights )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
sal_Bool bIsVertical = ((SdrObjCustomShape*)pCustomShape)->IsVerticalWriting();
|
|
|
|
sal_Int32 nVerticalOffset = rFWData.nMaxParagraphsPerTextArea > rTextArea.vParagraphs.size()
|
2004-04-02 13:03:55 +00:00
|
|
|
? rFWData.nSingleLineHeight / 2 : 0;
|
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIter( rTextArea.vParagraphs.begin() );
|
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIEnd( rTextArea.vParagraphs.end() );
|
|
|
|
while( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
const rtl::OUString& rText = aParagraphIter->aString;
|
2012-01-14 12:10:39 -02:00
|
|
|
if ( !rText.isEmpty() )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
// generating vcl/font
|
2011-01-10 16:11:35 +01:00
|
|
|
sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
|
2005-11-02 08:57:06 +00:00
|
|
|
Reference< i18n::XBreakIterator > xBI( EnhancedCustomShapeFontWork::GetBreakIterator() );
|
|
|
|
if ( xBI.is() )
|
|
|
|
{
|
|
|
|
nScriptType = xBI->getScriptType( rText, 0 );
|
|
|
|
if( i18n::ScriptType::WEAK == nScriptType )
|
|
|
|
{
|
2010-12-01 15:33:06 +00:00
|
|
|
sal_uInt16 nChg = 0;
|
2005-11-02 08:57:06 +00:00
|
|
|
nChg = (xub_StrLen)xBI->endOfScript( rText, nChg, nScriptType );
|
|
|
|
if( nChg < rText.getLength() )
|
|
|
|
nScriptType = xBI->getScriptType( rText, nChg );
|
|
|
|
else
|
|
|
|
nScriptType = i18n::ScriptType::LATIN;
|
|
|
|
}
|
|
|
|
}
|
2011-01-10 16:11:35 +01:00
|
|
|
sal_uInt16 nFntItm = EE_CHAR_FONTINFO;
|
2005-11-02 08:57:06 +00:00
|
|
|
if ( nScriptType == i18n::ScriptType::COMPLEX )
|
|
|
|
nFntItm = EE_CHAR_FONTINFO_CTL;
|
|
|
|
else if ( nScriptType == i18n::ScriptType::ASIAN )
|
|
|
|
nFntItm = EE_CHAR_FONTINFO_CJK;
|
|
|
|
SvxFontItem& rFontItem = (SvxFontItem&)pCustomShape->GetMergedItem( nFntItm );
|
2004-04-02 13:03:55 +00:00
|
|
|
Font aFont;
|
|
|
|
aFont.SetHeight( rFWData.nSingleLineHeight );
|
|
|
|
aFont.SetAlign( ALIGN_TOP );
|
|
|
|
|
|
|
|
aFont.SetName( rFontItem.GetFamilyName() );
|
|
|
|
aFont.SetFamily( rFontItem.GetFamily() );
|
|
|
|
aFont.SetStyleName( rFontItem.GetStyleName() );
|
|
|
|
aFont.SetOrientation( 0 );
|
|
|
|
|
2005-09-23 12:49:43 +00:00
|
|
|
SvxPostureItem& rPostureItem = (SvxPostureItem&)pCustomShape->GetMergedItem( EE_CHAR_ITALIC );
|
|
|
|
aFont.SetItalic( rPostureItem.GetPosture() );
|
|
|
|
|
|
|
|
SvxWeightItem& rWeightItem = (SvxWeightItem&)pCustomShape->GetMergedItem( EE_CHAR_WEIGHT );
|
|
|
|
aFont.SetWeight( rWeightItem.GetWeight() );
|
|
|
|
|
2004-04-02 13:03:55 +00:00
|
|
|
// initializing virtual device
|
|
|
|
VirtualDevice aVirDev( 1 );
|
|
|
|
aVirDev.SetMapMode( MAP_100TH_MM );
|
|
|
|
aVirDev.SetFont( aFont );
|
2005-02-21 15:17:39 +00:00
|
|
|
aVirDev.EnableRTL( sal_True );
|
|
|
|
if ( aParagraphIter->nFrameDirection == FRMDIR_HORI_RIGHT_TOP )
|
|
|
|
aVirDev.SetLayoutMode( TEXT_LAYOUT_BIDI_RTL );
|
2004-10-12 13:12:01 +00:00
|
|
|
|
|
|
|
SvxCharScaleWidthItem& rCharScaleWidthItem = (SvxCharScaleWidthItem&)pCustomShape->GetMergedItem( EE_CHAR_FONTWIDTH );
|
|
|
|
sal_uInt16 nCharScaleWidth = rCharScaleWidthItem.GetValue();
|
2005-10-05 12:23:02 +00:00
|
|
|
sal_Int32* pDXArry = NULL;
|
2004-10-12 13:12:01 +00:00
|
|
|
sal_Int32 nWidth = 0;
|
|
|
|
|
2005-02-21 15:17:39 +00:00
|
|
|
// VERTICAL
|
2004-04-02 13:03:55 +00:00
|
|
|
if ( bIsVertical )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
// vertical _> each single character needs to be rotated by 90
|
2004-04-02 13:03:55 +00:00
|
|
|
sal_Int32 i;
|
2004-10-12 13:12:01 +00:00
|
|
|
sal_Int32 nHeight = 0;
|
|
|
|
Rectangle aSingleCharacterUnion;
|
2004-04-02 13:03:55 +00:00
|
|
|
for ( i = 0; i < rText.getLength(); i++ )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
FWCharacterData aCharacterData;
|
2004-04-02 13:03:55 +00:00
|
|
|
rtl::OUString aCharText( (sal_Unicode)rText[ i ] );
|
2011-01-10 16:11:35 +01:00
|
|
|
if ( aVirDev.GetTextOutlines( aCharacterData.vOutlines, aCharText, 0, 0, STRING_LEN, sal_True, nWidth, pDXArry ) )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
sal_Int32 nTextWidth = aVirDev.GetTextWidth( aCharText, 0, STRING_LEN );
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter = aCharacterData.vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd = aCharacterData.vOutlines.end();
|
|
|
|
if ( aOutlineIter == aOutlineIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
nHeight += rFWData.nSingleLineHeight;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2004-10-12 13:12:01 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
while ( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
// rotating
|
|
|
|
aOutlineIter->Rotate( Point( nTextWidth / 2, rFWData.nSingleLineHeight / 2 ), 900 );
|
|
|
|
aCharacterData.aBoundRect.Union( aOutlineIter->GetBoundRect() );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
|
|
|
aOutlineIter = aCharacterData.vOutlines.begin();
|
|
|
|
aOutlineIEnd = aCharacterData.vOutlines.end();
|
|
|
|
while ( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
sal_Int32 nM = - aCharacterData.aBoundRect.Left() + nHeight;
|
|
|
|
aOutlineIter->Move( nM, 0 );
|
|
|
|
aCharacterData.aBoundRect.Move( nM, 0 );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
|
|
|
nHeight += aCharacterData.aBoundRect.GetWidth() + ( rFWData.nSingleLineHeight / 5 );
|
|
|
|
aSingleCharacterUnion.Union( aCharacterData.aBoundRect );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aParagraphIter->vCharacters.push_back( aCharacterData );
|
|
|
|
}
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
|
|
|
{
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
|
|
|
|
while ( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
aOutlineIter->Move( ( aSingleCharacterUnion.GetWidth() - aCharacterIter->aBoundRect.GetWidth() ) / 2, 0 );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
if ( ( nCharScaleWidth != 100 ) && nCharScaleWidth )
|
|
|
|
{ // applying character spacing
|
2005-10-05 12:23:02 +00:00
|
|
|
pDXArry = new sal_Int32[ rText.getLength() ];
|
2004-10-12 13:12:01 +00:00
|
|
|
aVirDev.GetTextArray( rText, pDXArry, 0, STRING_LEN );
|
|
|
|
FontMetric aFontMetric( aVirDev.GetFontMetric() );
|
|
|
|
aFont.SetWidth( (sal_Int32)( (double)aFontMetric.GetWidth() * ( (double)100 / (double)nCharScaleWidth ) ) );
|
|
|
|
aVirDev.SetFont( aFont );
|
|
|
|
}
|
|
|
|
FWCharacterData aCharacterData;
|
2011-01-10 16:11:35 +01:00
|
|
|
if ( aVirDev.GetTextOutlines( aCharacterData.vOutlines, rText, 0, 0, STRING_LEN, sal_True, nWidth, pDXArry ) )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
aParagraphIter->vCharacters.push_back( aCharacterData );
|
|
|
|
}
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2004-10-12 13:12:01 +00:00
|
|
|
delete[] pDXArry;
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
// veritcal alignment
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd ( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
2004-04-02 13:03:55 +00:00
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
PolyPolygon& rPolyPoly = *aOutlineIter++;
|
2004-04-02 13:03:55 +00:00
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
if ( nVerticalOffset )
|
|
|
|
rPolyPoly.Move( 0, nVerticalOffset );
|
|
|
|
|
|
|
|
// retrieving the boundrect for the paragraph
|
2005-02-21 15:17:39 +00:00
|
|
|
Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
|
|
|
|
aParagraphIter->aBoundRect.Union( aBoundRect );
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// updating the boundrect for the text area by merging the current paragraph boundrect
|
2004-10-12 13:12:01 +00:00
|
|
|
if ( aParagraphIter->aBoundRect.IsEmpty() )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
if ( rTextArea.aBoundRect.IsEmpty() )
|
|
|
|
rTextArea.aBoundRect = Rectangle( Point( 0, 0 ), Size( 1, rFWData.nSingleLineHeight ) );
|
|
|
|
else
|
|
|
|
rTextArea.aBoundRect.Bottom() += rFWData.nSingleLineHeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
Rectangle& rParagraphBoundRect = aParagraphIter->aBoundRect;
|
2004-04-02 13:03:55 +00:00
|
|
|
rTextArea.aBoundRect.Union( rParagraphBoundRect );
|
|
|
|
|
|
|
|
if ( bSameLetterHeights )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter( aCharacterIter->vOutlines.begin() );
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd( aCharacterIter->vOutlines.end() );
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
Rectangle aPolyPolyBoundRect( aOutlineIter->GetBoundRect() );
|
|
|
|
if ( aPolyPolyBoundRect.GetHeight() != rParagraphBoundRect.GetHeight() )
|
|
|
|
aOutlineIter->Scale( 1.0, (double)rParagraphBoundRect.GetHeight() / aPolyPolyBoundRect.GetHeight() );
|
|
|
|
aPolyPolyBoundRect = aOutlineIter->GetBoundRect();
|
|
|
|
sal_Int32 nMove = aPolyPolyBoundRect.Top() - rParagraphBoundRect.Top();
|
|
|
|
if ( nMove )
|
|
|
|
aOutlineIter->Move( 0, -nMove );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-10-12 13:12:01 +00:00
|
|
|
if ( bIsVertical )
|
|
|
|
nVerticalOffset -= rFWData.nSingleLineHeight;
|
|
|
|
else
|
|
|
|
nVerticalOffset += rFWData.nSingleLineHeight;
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetFontWorkOutline( FWData& rFWData, const SdrObject* pCustomShape )
|
|
|
|
{
|
|
|
|
SdrTextHorzAdjust eHorzAdjust( ((SdrTextHorzAdjustItem&)pCustomShape->GetMergedItem( SDRATTR_TEXT_HORZADJUST )).GetValue() );
|
|
|
|
SdrFitToSizeType eFTS( ((SdrTextFitToSizeTypeItem&)pCustomShape->GetMergedItem( SDRATTR_TEXT_FITTOSIZE )).GetValue() );
|
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
|
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
rFWData.nSingleLineHeight = (sal_Int32)( ( (double)pCustomShape->GetLogicRect().GetHeight()
|
|
|
|
/ rFWData.nMaxParagraphsPerTextArea ) * rFWData.fHorizontalTextScaling );
|
|
|
|
|
|
|
|
sal_Bool bSameLetterHeights = sal_False;
|
|
|
|
SdrCustomShapeGeometryItem& rGeometryItem = (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
|
2012-06-02 19:49:52 -05:00
|
|
|
const rtl::OUString sTextPath( "TextPath" );
|
|
|
|
const rtl::OUString sSameLetterHeights( "SameLetterHeights" );
|
2004-04-02 13:03:55 +00:00
|
|
|
com::sun::star::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( sTextPath, sSameLetterHeights );
|
|
|
|
if ( pAny )
|
|
|
|
*pAny >>= bSameLetterHeights;
|
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
while ( aTextAreaIter != aTextAreaIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
GetTextAreaOutline( rFWData, pCustomShape, *aTextAreaIter, bSameLetterHeights );
|
|
|
|
if ( eFTS == SDRTEXTFIT_ALLLINES )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
|
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
|
|
|
|
while ( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
sal_Int32 nParaWidth = aParagraphIter->aBoundRect.GetWidth();
|
2004-04-02 13:03:55 +00:00
|
|
|
if ( nParaWidth )
|
|
|
|
{
|
|
|
|
double fScale = (double)aTextAreaIter->aBoundRect.GetWidth() / nParaWidth;
|
2004-10-12 13:12:01 +00:00
|
|
|
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
aOutlineIter->Scale( fScale, 1.0 );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch( eHorzAdjust )
|
|
|
|
{
|
|
|
|
case SDRTEXTHORZADJUST_RIGHT :
|
|
|
|
case SDRTEXTHORZADJUST_CENTER:
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
|
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
|
|
|
|
while ( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
sal_Int32 nHorzDiff = 0;
|
|
|
|
if ( eHorzAdjust == SDRTEXTHORZADJUST_CENTER )
|
2004-10-12 13:12:01 +00:00
|
|
|
nHorzDiff = ( aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() ) / 2;
|
2004-04-02 13:03:55 +00:00
|
|
|
else if ( eHorzAdjust == SDRTEXTHORZADJUST_RIGHT )
|
2004-10-12 13:12:01 +00:00
|
|
|
nHorzDiff = ( aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() );
|
2004-04-02 13:03:55 +00:00
|
|
|
if ( nHorzDiff )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
aOutlineIter->Move( nHorzDiff, 0 );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case SDRTEXTHORZADJUST_BLOCK : break; // don't know
|
|
|
|
case SDRTEXTHORZADJUST_LEFT : break; // already left aligned -> nothing to do
|
|
|
|
}
|
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aTextAreaIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-14 12:14:19 +00:00
|
|
|
basegfx::B2DPolyPolygon GetOutlinesFromShape2d( const SdrObject* pShape2d )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2006-11-14 12:14:19 +00:00
|
|
|
basegfx::B2DPolyPolygon aOutlines2d;
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
SdrObjListIter aObjListIter( *pShape2d, IM_DEEPWITHGROUPS );
|
|
|
|
while( aObjListIter.IsMore() )
|
|
|
|
{
|
|
|
|
SdrObject* pPartObj = aObjListIter.Next();
|
|
|
|
if ( pPartObj->ISA( SdrPathObj ) )
|
|
|
|
{
|
2006-11-14 12:14:19 +00:00
|
|
|
basegfx::B2DPolyPolygon aCandidate(((SdrPathObj*)pPartObj)->GetPathPoly());
|
2005-01-07 08:22:45 +00:00
|
|
|
if(aCandidate.areControlPointsUsed())
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2006-11-14 12:14:19 +00:00
|
|
|
aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2005-01-07 08:22:45 +00:00
|
|
|
aOutlines2d.append(aCandidate);
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-03 09:34:18 +00:00
|
|
|
|
2004-04-02 13:03:55 +00:00
|
|
|
return aOutlines2d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CalcDistances( const Polygon& rPoly, std::vector< double >& rDistances )
|
|
|
|
{
|
|
|
|
sal_uInt16 i, nCount = rPoly.GetSize();
|
|
|
|
if ( nCount > 1 )
|
|
|
|
{
|
|
|
|
for ( i = 0; i < nCount; i++ )
|
|
|
|
{
|
|
|
|
double fDistance = i ? ((Polygon&)rPoly).CalcDistance( i, i - 1 ) : 0.0;
|
|
|
|
rDistances.push_back( fDistance );
|
|
|
|
}
|
|
|
|
std::partial_sum( rDistances.begin(), rDistances.end(), rDistances.begin() );
|
|
|
|
double fLength = rDistances[ rDistances.size() - 1 ];
|
|
|
|
if ( fLength > 0.0 )
|
|
|
|
{
|
|
|
|
std::vector< double >::iterator aIter = rDistances.begin();
|
|
|
|
std::vector< double >::iterator aEnd = rDistances.end();
|
|
|
|
while ( aIter != aEnd )
|
|
|
|
*aIter++ /= fLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-19 13:56:53 +00:00
|
|
|
void InsertMissingOutlinePoints( const Polygon& /*rOutlinePoly*/, const std::vector< double >& rDistances, const Rectangle& rTextAreaBoundRect, Polygon& rPoly )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
sal_uInt16 i = 0;
|
2006-10-12 11:02:19 +00:00
|
|
|
double fLastDistance = 0.0;
|
2004-04-02 13:03:55 +00:00
|
|
|
for ( i = 0; i < rPoly.GetSize(); i++ )
|
|
|
|
{
|
|
|
|
Point& rPoint = rPoly[ i ];
|
|
|
|
double fDistance = (double)( rPoint.X() - rTextAreaBoundRect.Left() ) / (double)rTextAreaBoundRect.GetWidth();
|
|
|
|
if ( i )
|
|
|
|
{
|
|
|
|
if ( fDistance > fLastDistance )
|
|
|
|
{
|
|
|
|
std::vector< double >::const_iterator aIter = std::upper_bound( rDistances.begin(), rDistances.end(), fLastDistance );
|
|
|
|
if ( aIter != rDistances.end() && ( *aIter > fLastDistance ) && ( *aIter < fDistance ) )
|
|
|
|
{
|
|
|
|
Point& rPt0 = rPoly[ i - 1 ];
|
|
|
|
sal_Int32 fX = rPoint.X() - rPt0.X();
|
|
|
|
sal_Int32 fY = rPoint.Y() - rPt0.Y();
|
|
|
|
double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
|
|
|
|
rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
|
|
|
|
fDistance = *aIter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( fDistance < fLastDistance )
|
|
|
|
{
|
|
|
|
std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fLastDistance );
|
|
|
|
if ( aIter-- != rDistances.begin() )
|
|
|
|
{
|
|
|
|
if ( ( *aIter > fDistance ) && ( *aIter < fLastDistance ) )
|
|
|
|
{
|
|
|
|
Point& rPt0 = rPoly[ i - 1 ];
|
|
|
|
sal_Int32 fX = rPoint.X() - rPt0.X();
|
|
|
|
sal_Int32 fY = rPoint.Y() - rPt0.Y();
|
|
|
|
double fd = ( 1.0 / ( fDistance - fLastDistance ) ) * ( *aIter - fLastDistance );
|
|
|
|
rPoly.Insert( i, Point( (sal_Int32)( rPt0.X() + fX * fd ), (sal_Int32)( rPt0.Y() + fY * fd ) ) );
|
|
|
|
fDistance = *aIter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fLastDistance = fDistance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetPoint( const Polygon& rPoly, const std::vector< double >& rDistances, const double& fX, double& fx1, double& fy1 )
|
|
|
|
{
|
|
|
|
fy1 = fx1 = 0.0;
|
Better shading algo for customshapes, better gradients
Some custom shapes can have shaded parts, like for example 3d can,
the bevelled buttons etc. Those shaded colors are calculated
internally, and have been way off at times. Now using HSV color
space & the originally documented luminance modifications in steps
of 10 percent. Compared to MSO, still no 100 percent match, but
that seems due to gamma correction there.
Additionally, starting with MSO12, gradients on those shaded surfaces
look much better; adapted code to display gradients equally nice.
Note that most of this patch also applies to ooxml import; note as
well that customshapes from *all* kind of input files (including ODF
docs) now look different than before; no real way of changing this
in a backward-compatible way, since behaviour of custom shapes is
mandated (mostly) by internal tables, and not stored in a file.
Applies patches/dev300/ppt-customshape-shading-fix (much of it was
accepted at OOo already, via i#102797)
Applies patches/dev300/ppt-customshape-shading-fix.diff: fixed prob
with line arrows - the extra-added single point polygons lead to
extra arrows randomly around the custom shape. i#105654
2010-10-26 23:04:44 +02:00
|
|
|
if ( rPoly.GetSize() > 1 )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
std::vector< double >::const_iterator aIter = std::lower_bound( rDistances.begin(), rDistances.end(), fX );
|
2006-10-12 11:02:19 +00:00
|
|
|
sal_uInt16 nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
|
2004-04-02 13:03:55 +00:00
|
|
|
if ( aIter == rDistances.end() )
|
|
|
|
nIdx--;
|
|
|
|
const Point& rPt = rPoly[ nIdx ];
|
|
|
|
fx1 = rPt.X();
|
|
|
|
fy1 = rPt.Y();
|
|
|
|
if ( nIdx && ( aIter != rDistances.end() ) && ( *aIter != fX ) )
|
|
|
|
{
|
2006-10-12 11:02:19 +00:00
|
|
|
nIdx = sal::static_int_cast<sal_uInt16>( std::distance( rDistances.begin(), aIter ) );
|
2004-04-02 13:03:55 +00:00
|
|
|
double fDist0 = *( aIter - 1 );
|
|
|
|
double fd = ( 1.0 / ( *aIter - fDist0 ) ) * ( fX - fDist0 );
|
|
|
|
const Point& rPt2 = rPoly[ nIdx - 1 ];
|
|
|
|
double fWidth = rPt.X() - rPt2.X();
|
|
|
|
double fHeight= rPt.Y() - rPt2.Y();
|
|
|
|
fWidth *= fd;
|
|
|
|
fHeight*= fd;
|
|
|
|
fx1 = rPt2.X() + fWidth;
|
|
|
|
fy1 = rPt2.Y() + fHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FitTextOutlinesToShapeOutlines( const PolyPolygon& aOutlines2d, FWData& rFWData )
|
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin();
|
|
|
|
std::vector< FWTextArea >::iterator aTextAreaIEnd = rFWData.vTextAreas.end();
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
sal_uInt16 nOutline2dIdx = 0;
|
2004-10-12 13:12:01 +00:00
|
|
|
while( aTextAreaIter != aTextAreaIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
Rectangle rTextAreaBoundRect = aTextAreaIter->aBoundRect;
|
|
|
|
sal_Int32 nLeft = rTextAreaBoundRect.Left();
|
|
|
|
sal_Int32 nTop = rTextAreaBoundRect.Top();
|
|
|
|
sal_Int32 nWidth = rTextAreaBoundRect.GetWidth();
|
|
|
|
sal_Int32 nHeight= rTextAreaBoundRect.GetHeight();
|
|
|
|
if ( rFWData.bSingleLineMode && nHeight && nWidth )
|
|
|
|
{
|
|
|
|
if ( nOutline2dIdx >= aOutlines2d.Count() )
|
|
|
|
break;
|
|
|
|
const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
|
|
|
|
const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
|
2009-09-09 09:19:53 +00:00
|
|
|
if ( nPointCount > 1 )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
std::vector< double > vDistances;
|
|
|
|
vDistances.reserve( nPointCount );
|
|
|
|
CalcDistances( rOutlinePoly, vDistances );
|
2011-07-31 01:17:59 +02:00
|
|
|
if ( !vDistances.empty() )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() );
|
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() );
|
|
|
|
while( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
|
|
|
PolyPolygon& rPolyPoly = *aOutlineIter;
|
|
|
|
Rectangle aBoundRect( rPolyPoly.GetBoundRect() );
|
|
|
|
double fx1 = aBoundRect.Left() - nLeft;
|
|
|
|
double fx2 = aBoundRect.Right() - nLeft;
|
|
|
|
double fy1, fy2;
|
|
|
|
double fM1 = fx1 / (double)nWidth;
|
|
|
|
double fM2 = fx2 / (double)nWidth;
|
|
|
|
|
|
|
|
GetPoint( rOutlinePoly, vDistances, fM1, fx1, fy1 );
|
|
|
|
GetPoint( rOutlinePoly, vDistances, fM2, fx2, fy2 );
|
|
|
|
|
|
|
|
double fvx = ( fy2 - fy1 );
|
|
|
|
double fvy = - ( fx2 - fx1 );
|
|
|
|
fx1 = fx1 + ( ( fx2 - fx1 ) * 0.5 );
|
|
|
|
fy1 = fy1 + ( ( fy2 - fy1 ) * 0.5 );
|
|
|
|
|
|
|
|
double fAngle = atan2( -fvx, -fvy );
|
|
|
|
double fL = hypot( fvx, fvy );
|
|
|
|
fvx = fvx / fL;
|
|
|
|
fvy = fvy / fL;
|
|
|
|
fL = (double)( aTextAreaIter->aBoundRect.GetHeight() / 2.0 + aTextAreaIter->aBoundRect.Top() ) - aParagraphIter->aBoundRect.Center().Y();
|
|
|
|
fvx *= fL;
|
|
|
|
fvy *= fL;
|
|
|
|
rPolyPoly.Rotate( Point( aBoundRect.Center().X(), aParagraphIter->aBoundRect.Center().Y() ), sin( fAngle ), cos( fAngle ) );
|
|
|
|
rPolyPoly.Move( (sal_Int32)( ( fx1 + fvx )- aBoundRect.Center().X() ), (sal_Int32)( ( fy1 + fvy ) - aParagraphIter->aBoundRect.Center().Y() ) );
|
|
|
|
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( ( nOutline2dIdx + 1 ) >= aOutlines2d.Count() )
|
|
|
|
break;
|
|
|
|
const Polygon& rOutlinePoly( aOutlines2d[ nOutline2dIdx++ ] );
|
|
|
|
const Polygon& rOutlinePoly2( aOutlines2d[ nOutline2dIdx++ ] );
|
|
|
|
const sal_uInt16 nPointCount = rOutlinePoly.GetSize();
|
|
|
|
const sal_uInt16 nPointCount2 = rOutlinePoly2.GetSize();
|
2009-09-09 09:19:53 +00:00
|
|
|
if ( ( nPointCount > 1 ) && ( nPointCount2 > 1 ) )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
|
|
|
std::vector< double > vDistances;
|
|
|
|
vDistances.reserve( nPointCount );
|
|
|
|
std::vector< double > vDistances2;
|
|
|
|
vDistances2.reserve( nPointCount2 );
|
|
|
|
CalcDistances( rOutlinePoly, vDistances );
|
|
|
|
CalcDistances( rOutlinePoly2, vDistances2 );
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
|
|
|
|
std::vector< FWParagraphData >::iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
|
|
|
|
while( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
PolyPolygon& rPolyPoly = *aOutlineIter;
|
|
|
|
sal_uInt16 i, nPolyCount = rPolyPoly.Count();
|
|
|
|
for ( i = 0; i < nPolyCount; i++ )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-11-03 09:34:18 +00:00
|
|
|
// #i35928#
|
2006-11-14 12:14:19 +00:00
|
|
|
basegfx::B2DPolygon aCandidate(rPolyPoly[ i ].getB2DPolygon());
|
2004-11-03 09:34:18 +00:00
|
|
|
|
2007-07-18 09:52:27 +00:00
|
|
|
if(aCandidate.areControlPointsUsed())
|
2004-11-03 09:34:18 +00:00
|
|
|
{
|
2006-11-14 12:14:19 +00:00
|
|
|
aCandidate = basegfx::tools::adaptiveSubdivideByAngle(aCandidate);
|
2004-11-03 09:34:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// create local polygon copy to work on
|
|
|
|
Polygon aLocalPoly(aCandidate);
|
|
|
|
|
|
|
|
InsertMissingOutlinePoints( rOutlinePoly, vDistances, rTextAreaBoundRect, aLocalPoly );
|
|
|
|
InsertMissingOutlinePoints( rOutlinePoly2, vDistances2, rTextAreaBoundRect, aLocalPoly );
|
|
|
|
|
2006-06-19 13:56:53 +00:00
|
|
|
sal_uInt16 j, _nPointCount = aLocalPoly.GetSize();
|
|
|
|
for ( j = 0; j < _nPointCount; j++ )
|
2004-10-12 13:12:01 +00:00
|
|
|
{
|
2004-11-03 09:34:18 +00:00
|
|
|
Point& rPoint = aLocalPoly[ j ];
|
2004-10-12 13:12:01 +00:00
|
|
|
rPoint.X() -= nLeft;
|
|
|
|
rPoint.Y() -= nTop;
|
|
|
|
double fX = (double)rPoint.X() / (double)nWidth;
|
|
|
|
double fY = (double)rPoint.Y() / (double)nHeight;
|
|
|
|
|
|
|
|
double fx1, fy1, fx2, fy2;
|
|
|
|
GetPoint( rOutlinePoly, vDistances, fX, fx1, fy1 );
|
|
|
|
GetPoint( rOutlinePoly2, vDistances2, fX, fx2, fy2 );
|
|
|
|
double fWidth = fx2 - fx1;
|
|
|
|
double fHeight= fy2 - fy1;
|
|
|
|
rPoint.X() = (sal_Int32)( fx1 + fWidth * fY );
|
|
|
|
rPoint.Y() = (sal_Int32)( fy1 + fHeight* fY );
|
|
|
|
}
|
2004-11-03 09:34:18 +00:00
|
|
|
|
|
|
|
// write back polygon
|
|
|
|
rPolyPoly[ i ] = aLocalPoly;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aTextAreaIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SdrObject* CreateSdrObjectFromParagraphOutlines( const FWData& rFWData, const SdrObject* pCustomShape )
|
|
|
|
{
|
|
|
|
SdrObject* pRet = NULL;
|
2012-08-15 09:46:56 +02:00
|
|
|
basegfx::B2DPolyPolygon aPolyPoly;
|
2011-07-31 01:17:59 +02:00
|
|
|
if ( !rFWData.vTextAreas.empty() )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWTextArea >::const_iterator aTextAreaIter = rFWData.vTextAreas.begin();
|
|
|
|
std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end();
|
|
|
|
while ( aTextAreaIter != aTextAreaIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWParagraphData >::const_iterator aParagraphIter = aTextAreaIter->vParagraphs.begin();
|
|
|
|
std::vector< FWParagraphData >::const_iterator aParagraphIEnd = aTextAreaIter->vParagraphs.end();
|
|
|
|
while ( aParagraphIter != aParagraphIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< FWCharacterData >::const_iterator aCharacterIter( aParagraphIter->vCharacters.begin() );
|
|
|
|
std::vector< FWCharacterData >::const_iterator aCharacterIEnd( aParagraphIter->vCharacters.end() );
|
|
|
|
while ( aCharacterIter != aCharacterIEnd )
|
2004-04-02 13:03:55 +00:00
|
|
|
{
|
2004-10-12 13:12:01 +00:00
|
|
|
std::vector< PolyPolygon >::const_iterator aOutlineIter = aCharacterIter->vOutlines.begin();
|
|
|
|
std::vector< PolyPolygon >::const_iterator aOutlineIEnd = aCharacterIter->vOutlines.end();
|
|
|
|
while( aOutlineIter != aOutlineIEnd )
|
|
|
|
{
|
2012-08-15 09:46:56 +02:00
|
|
|
aPolyPoly.append( aOutlineIter->getB2DPolyPolygon() );
|
2010-12-29 09:52:22 +01:00
|
|
|
++aOutlineIter;
|
2004-10-12 13:12:01 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aCharacterIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aParagraphIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
2010-12-29 09:52:22 +01:00
|
|
|
++aTextAreaIter;
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
|
2012-08-15 09:46:56 +02:00
|
|
|
pRet = new SdrPathObj( OBJ_POLY, aPolyPoly );
|
|
|
|
|
2004-10-12 13:12:01 +00:00
|
|
|
SfxItemSet aSet( pCustomShape->GetMergedItemSet() );
|
|
|
|
aSet.ClearItem( SDRATTR_TEXTDIRECTION ); //SJ: vertical writing is not required, by removing this item no outliner is created
|
2004-11-18 10:03:07 +00:00
|
|
|
aSet.Put(SdrShadowItem(sal_False)); // #i37011# NO shadow for FontWork geometry
|
2004-10-12 13:12:01 +00:00
|
|
|
pRet->SetMergedItemSet( aSet ); // * otherwise we would crash, because the outliner tries to create a Paraobject, but there is no model
|
2004-04-02 13:03:55 +00:00
|
|
|
}
|
|
|
|
return pRet;
|
|
|
|
}
|
2005-11-02 08:57:06 +00:00
|
|
|
|
2012-10-15 15:20:48 +02:00
|
|
|
Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::mxBreakIterator = 0;
|
2005-11-02 08:57:06 +00:00
|
|
|
|
|
|
|
Reference < i18n::XBreakIterator > EnhancedCustomShapeFontWork::GetBreakIterator()
|
|
|
|
{
|
|
|
|
if ( !mxBreakIterator.is() )
|
|
|
|
{
|
2012-10-15 15:20:48 +02:00
|
|
|
Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
|
|
|
|
mxBreakIterator = i18n::BreakIterator::create(xContext);
|
2005-11-02 08:57:06 +00:00
|
|
|
}
|
|
|
|
return mxBreakIterator;
|
|
|
|
}
|
2004-04-02 13:03:55 +00:00
|
|
|
|
|
|
|
SdrObject* EnhancedCustomShapeFontWork::CreateFontWork( const SdrObject* pShape2d, const SdrObject* pCustomShape )
|
|
|
|
{
|
|
|
|
SdrObject* pRet = NULL;
|
|
|
|
|
|
|
|
PolyPolygon aOutlines2d( GetOutlinesFromShape2d( pShape2d ) );
|
|
|
|
sal_uInt16 nOutlinesCount2d = aOutlines2d.Count();
|
|
|
|
if ( nOutlinesCount2d )
|
|
|
|
{
|
|
|
|
FWData aFWData;
|
|
|
|
if ( InitializeFontWorkData( pCustomShape, nOutlinesCount2d, aFWData ) )
|
|
|
|
{
|
|
|
|
/* retrieves the horizontal scaling factor that has to be used
|
|
|
|
to fit each paragraph text into its corresponding 2d outline */
|
|
|
|
CalculateHorizontalScalingFactor( pCustomShape, aFWData, aOutlines2d );
|
|
|
|
|
|
|
|
/* retrieving the Outlines for the each Paragraph. */
|
|
|
|
|
|
|
|
GetFontWorkOutline( aFWData, pCustomShape );
|
|
|
|
|
|
|
|
FitTextOutlinesToShapeOutlines( aOutlines2d, aFWData );
|
|
|
|
|
|
|
|
pRet = CreateSdrObjectFromParagraphOutlines( aFWData, pCustomShape );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return pRet;
|
|
|
|
}
|
2010-10-12 15:53:47 +02:00
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|