Kaydet (Commit) a143d7d1 authored tarafından Daniel Sikeler's avatar Daniel Sikeler Kaydeden (comit) Michael Stahl

De-/Increase fontsize when multi-sized text

I did the changes proposed in https://gerrit.libreoffice.org/#/c/11857/
I also tested it with a mixture of CJK and CTL text

Change-Id: Ic75f557b8c0a68f43abbd8c28b2222945e9361b7
Reviewed-on: https://gerrit.libreoffice.org/13152Reviewed-by: 's avatarMichael Stahl <mstahl@redhat.com>
Tested-by: 's avatarMichael Stahl <mstahl@redhat.com>
üst ababde70
......@@ -235,16 +235,11 @@ public:
void SetAttrItem( const SfxPoolItem&, sal_uInt16 nFlags = 0 );
void SetAttrSet( const SfxItemSet&, sal_uInt16 nFlags = 0, SwPaM* pCrsr = NULL );
/** Get all items of one type in the current selection.
/** Get RES_CHRATR_* items of one type in the current selection.
* @param nWhich WhichId of the collected items.
* @return Vector with the items.*/
std::vector<const SfxPoolItem*> GetCurItem( sal_uInt16 nWhich );
/** Splits the current SwPaM in smaller ones.
* The borders of an itemtype are used as separator. The SwPaMs must be deleted after use.
* @param nWhich WhichId of the item to separate at.
* @return Vector with the smaller SwPaMs*/
std::vector<SwPaM*> GetSplitPaM( sal_uInt16 nWhich );
* If parts of the selection have different scripttypes, the items with corresponding WhichIds are also collected.
* @return a vector of pairs. The pair contains a SfxPoolItem and a SwPaM, in which the item is valid and can be changed. */
std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM>>> GetItemWithPaM( sal_uInt16 nWhich );
/**
* Get the paragraph format attribute(s) of the current selection.
......
......@@ -21,7 +21,6 @@
#include <editeng/tstpitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/scripttypeitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <com/sun/star/i18n/ScriptType.hpp>
#include <txatbase.hxx>
#include <txtftn.hxx>
......@@ -283,178 +282,107 @@ SwTxtFmtColl* SwEditShell::GetPaMTxtFmtColl( SwPaM* pPaM ) const
return NULL;
}
std::vector<const SfxPoolItem*> SwEditShell::GetCurItem( sal_uInt16 nWhich )
std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> SwEditShell::GetItemWithPaM( sal_uInt16 nWhich )
{
std::vector<const SfxPoolItem*> vItem;
std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItem;
SwPaM* pPaM = GetCrsr();
SwPaM* pStartPaM = pPaM;
do { // for all the point and mark (selections)
// get the start and the end node of the current selection
sal_uLong nSttNd = pPaM->GetMark()->nNode.GetIndex(),
nEndNd = pPaM->GetPoint()->nNode.GetIndex();
sal_Int32 nSttCnt = pPaM->GetMark()->nContent.GetIndex();
sal_Int32 nEndCnt = pPaM->GetPoint()->nContent.GetIndex();
sal_uLong nSttNd = pPaM->Start()->nNode.GetIndex(),
nEndNd = pPaM->End()->nNode.GetIndex();
sal_Int32 nSttCnt = pPaM->Start()->nContent.GetIndex();
sal_Int32 nEndCnt = pPaM->End()->nContent.GetIndex();
// reverse start and end if there number aren't sorted correctly
if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
{
std::swap(nSttNd, nEndNd);
std::swap(nSttCnt, nEndCnt);
}
SwPaM* pNewPaM = 0;
const SfxPoolItem* pItem = 0;
// for all the nodes in the current selection
for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
{
SwNode* pNd = GetDoc()->GetNodes()[ n ];
switch( pNd->GetNodeType() )
if( pNd->IsTxtNode() )
{
case ND_TEXTNODE:
SwTxtNode* pTxtNd = static_cast< SwTxtNode* >( pNd );
const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
const sal_Int32 nEnd = (n == nEndNd)
? nEndCnt : pTxtNd->GetTxt().getLength();
const SwScriptInfo* pScriptInfo = SwScriptInfo::GetScriptInfo( *pTxtNd );
sal_uInt8 nScript = pScriptInfo ? pScriptInfo->ScriptType( nStt ) : css::i18n::ScriptType::WEAK;
nWhich = GetWhichOfScript( nWhich, nScript );
// item from attribute set
if( pTxtNd->HasSwAttrSet() )
{
SwTxtNode* pTxtNd = static_cast<SwTxtNode*>(pNd);
const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
const sal_Int32 nEnd = (n == nEndNd)
? nEndCnt : pTxtNd->GetTxt().getLength();
pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
pItem = pTxtNd->GetSwAttrSet().GetItem( nWhich );
vItem.push_back( std::make_pair( pItem, std::unique_ptr<SwPaM>(pNewPaM) ) );
}
// item from attribute set or default item
if ( pTxtNd->HasSwAttrSet() )
{
const SwAttrSet aSet = pTxtNd->GetSwAttrSet();
vItem.push_back( &(aSet.GetSize()) );
}
// items with limited range
if ( pTxtNd->HasHints() )
if( !pTxtNd->HasHints() )
continue;
// items with limited range
const size_t nSize = pTxtNd->GetpSwpHints()->Count();
for( size_t m = 0; m < nSize; m++ )
{
const SwTxtAttr* pHt = (*pTxtNd->GetpSwpHints())[m];
if( pHt->Which() == RES_TXTATR_AUTOFMT ||
pHt->Which() == RES_TXTATR_CHARFMT ||
pHt->Which() == RES_TXTATR_INETFMT )
{
const size_t nSize = pTxtNd->GetpSwpHints()->Count();
for (size_t m = 0; m < nSize; m++)
const sal_Int32 nAttrStart = pHt->GetStart();
const sal_Int32* pAttrEnd = pHt->End();
// Ignore items not in selection
if( nAttrStart > nEnd )
break;
if( *pAttrEnd <= nStt )
continue;
nScript = pScriptInfo ? pScriptInfo->ScriptType( nStt ) : css::i18n::ScriptType::WEAK;
nWhich = GetWhichOfScript( nWhich, nScript );
const SfxItemSet* pAutoSet = CharFmt::GetItemSet( pHt->GetAttr() );
if( pAutoSet )
{
const SwTxtAttr* pHt = (*pTxtNd->GetpSwpHints())[m];
if ( pHt->Which() == RES_TXTATR_AUTOFMT )
SfxItemIter aItemIter( *pAutoSet );
pItem = aItemIter.GetCurItem();
while( pItem )
{
const sal_Int32 nAttrStart = pHt->GetStart();
const sal_Int32* pAttrEnd = pHt->End();
// Ignore items not in selection
if ( nAttrStart > nEnd )
break;
if ( !pAttrEnd || *pAttrEnd <= nStt )
continue;
boost::scoped_ptr< SfxItemIter > pItemIter;
const SfxPoolItem* pItem = 0;
const SfxItemSet* pAutoSet =
CharFmt::GetItemSet ( pHt->GetAttr() );
if ( pAutoSet )
if( pItem->Which() == nWhich )
{
pItemIter.reset( new SfxItemIter( *pAutoSet ));
pItem = pItemIter->GetCurItem();
while ( pItem )
{
if ( pItem->Which() == nWhich )
{
vItem.push_back( pItem );
break;
}
pItem = pItemIter->NextItem();
}
sal_Int32 nStart = 0, nStop = 0;
if( nAttrStart < nStt ) //Attribut starts before selection
nStart = nStt;
else
nStart = nAttrStart;
if( *pAttrEnd > nEnd ) //Attribut ends after selection
nStop = nEnd;
else
nStop = *pAttrEnd;
pNewPaM = new SwPaM(*pNd, nStart, *pNd, nStop);
vItem.push_back( std::make_pair( pItem, std::unique_ptr<SwPaM>(pNewPaM) ) );
break;
}
pItem = aItemIter.NextItem();
}
// default item
if( !pItem && !pTxtNd->HasSwAttrSet() )
{
pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
pItem = pAutoSet->GetPool()->GetPoolDefaultItem( nWhich );
vItem.push_back( std::make_pair( pItem, std::unique_ptr<SwPaM>(pNewPaM)) );
}
}
}
}
break;
case ND_GRFNODE:
case ND_OLENODE:
break;
default:
pNd = 0;
}
}
} while ( ( pPaM = static_cast<SwPaM*>(pPaM->GetNext()) ) != pStartPaM );
return vItem;
}
std::vector<SwPaM*> SwEditShell::GetSplitPaM( sal_uInt16 nWhich)
{
std::vector<SwPaM*> vPaMs;
SwPaM* pPaM = GetCrsr();
SwPaM* pStartPaM = pPaM;
do { // for all the point and mark (selections)
// get the start and the end node of the current selection
sal_uLong nSttNd = pPaM->GetMark()->nNode.GetIndex(),
nEndNd = pPaM->GetPoint()->nNode.GetIndex();
sal_Int32 nSttCnt = pPaM->GetMark()->nContent.GetIndex();
sal_Int32 nEndCnt = pPaM->GetPoint()->nContent.GetIndex();
// reverse start and end if there number aren't sorted correctly
if( nSttNd > nEndNd || ( nSttNd == nEndNd && nSttCnt > nEndCnt ))
{
std::swap(nSttNd, nEndNd);
std::swap(nSttCnt, nEndCnt);
}
// for all the nodes in the current selection
for( sal_uLong n = nSttNd; n <= nEndNd; ++n )
{
SwNode* pNd = GetDoc()->GetNodes()[ n ];
switch( pNd->GetNodeType() )
{
case ND_TEXTNODE:
{
SwTxtNode* pTxtNd = static_cast<SwTxtNode*>(pNd);
const sal_Int32 nStt = (n == nSttNd) ? nSttCnt : 0;
const sal_Int32 nEnd = (n == nEndNd)
? nEndCnt : pTxtNd->GetTxt().getLength();
if ( pTxtNd->HasSwAttrSet() )
{
SwPaM* pNewPaM = new SwPaM(*pNd, nStt, *pNd, nEnd);
vPaMs.push_back( pNewPaM );
}
if ( pTxtNd->HasHints() )
{
const size_t nSize = pTxtNd->GetpSwpHints()->Count();
for (size_t m = 0; m < nSize; m++)
{
const SwTxtAttr* pHt = (*pTxtNd->GetpSwpHints())[m];
const SfxItemSet* pAutoSet =
CharFmt::GetItemSet ( pHt->GetAttr() );
if (isTXTATR_NOEND(pHt->Which()) || !pAutoSet || !pAutoSet->HasItem(nWhich))
continue;
const sal_Int32 nAttrStart = pHt->GetStart();
const sal_Int32* pAttrEnd = pHt->End();
if ( nAttrStart > nEnd )
break;
if ( !pAttrEnd || *pAttrEnd <= nStt )
continue;
sal_Int32 nStart = 0, nStop = 0;
if ( nAttrStart < nStt ) //Attribut starts before selection
nStart = nStt;
else
nStart = nAttrStart;
if ( *pAttrEnd > nEnd ) //Attribut ends after selection
nStop = nEnd;
else
nStop = *pAttrEnd;
SwPaM* pNewPaM = new SwPaM(*pNd, nStart, *pNd, nStop);
vPaMs.push_back( pNewPaM );
}
}
}
break;
case ND_GRFNODE:
case ND_OLENODE:
break;
default:
pNd = 0;
}
}
} while ( ( pPaM = static_cast<SwPaM*>(pPaM->GetNext()) ) != pStartPaM );
return vPaMs;
}
bool SwEditShell::GetCurFtn( SwFmtFtn* pFillFtn )
{
// The cursor must be positioned on the current footnotes anchor:
......
......@@ -225,29 +225,25 @@ void SwTextShell::ExecCharAttrArgs(SfxRequest &rReq)
sal_uInt16 nScriptTypes = rWrtSh.GetScriptType();
const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
aSetItem.GetItemOfScript( nScriptTypes ) ) );
std::vector<SwPaM*> vPaM;
std::vector<const SfxPoolItem*> vItem;
std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItems;
if ( pSize ) // selected text has one size
{
vItem.push_back( pSize );
// must create new one, otherwise document is without pam
SwPaM* pPaM = rWrtSh.GetCrsr();
vPaM.push_back( new SwPaM( *(pPaM->GetMark()), *(pPaM->GetPoint()) ) );
vItems.push_back( std::make_pair( pSize, std::unique_ptr<SwPaM>(new SwPaM( *(pPaM->GetMark()), *(pPaM->GetPoint()))) ) );
}
else
{
vPaM = rWrtSh.GetSplitPaM( RES_CHRATR_FONTSIZE );
vItem = rWrtSh.GetCurItem ( RES_CHRATR_FONTSIZE );
}
std::vector<SwPaM*>::iterator iPaM = vPaM.begin();
std::vector<const SfxPoolItem*>::const_iterator iItem = vItem.begin();
vItems = rWrtSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
rWrtSh.StartUndo( UNDO_INSATTR, NULL);
for ( ; iPaM != vPaM.end() && iItem != vItem.end(); ++iPaM, ++iItem )
for( std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >& iPair : vItems )
{
rWrtSh.GetPaMAttr( *iPaM, aSetItem.GetItemSet() );
std::unique_ptr<SwPaM> pPaM = std::move(iPair.second);
const SfxPoolItem* pItem = iPair.first;
rWrtSh.GetPaMAttr( pPaM.get(), aSetItem.GetItemSet() );
aAttrSet.SetRanges( aSetItem.GetItemSet().GetRanges() );
pSize = static_cast<const SvxFontHeightItem*>( *iItem );
pSize = static_cast<const SvxFontHeightItem*>( pItem );
if (pSize)
{
SvxFontHeightItem aSize(*pSize);
......@@ -265,9 +261,8 @@ void SwTextShell::ExecCharAttrArgs(SfxRequest &rReq)
if( pColl )
pColl->SetFmtAttr( aAttrSet );
else
rWrtSh.SetAttrSet( aAttrSet, 0, *iPaM );
rWrtSh.SetAttrSet( aAttrSet, 0, pPaM.get() );
}
delete *iPaM;
}
rWrtSh.EndUndo( UNDO_INSATTR, NULL);
rReq.Done();
......@@ -627,21 +622,28 @@ void SwTextShell::GetAttrState(SfxItemSet &rSet)
const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
aSetItem.GetItemOfScript( rSh.GetScriptType() ) ) );
std::vector<const SfxPoolItem*> vFontHeight;
if( pSize ) // selection is of one size
vFontHeight.push_back( pSize );
else
vFontHeight = rSh.GetCurItem( RES_CHRATR_FONTSIZE );
for ( const SfxPoolItem* pIt : vFontHeight )
{
pSize = static_cast<const SvxFontHeightItem*>(pIt);
sal_uInt32 nSize = pSize->GetHeight();
if( nSize == nFontMaxSz )
rSet.DisableItem( FN_GROW_FONT_SIZE );
else if( nSize == nFontInc )
rSet.DisableItem( FN_SHRINK_FONT_SIZE );
}
else
{
std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >>
vFontHeight = rSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
for ( std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM>>& pIt : vFontHeight )
{
pSize = static_cast<const SvxFontHeightItem*>( pIt.first );
sal_uInt32 nSize = pSize->GetHeight();
if( nSize == nFontMaxSz )
rSet.DisableItem( FN_GROW_FONT_SIZE );
else if( nSize == nFontInc )
rSet.DisableItem( FN_SHRINK_FONT_SIZE );
}
}
nSlot = 0;
}
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment