Files
libreoffice/sw/source/core/objectpositioning/ascharanchoredobjectposition.cxx
Michael Meeks caaeb0a046 re-base on ALv2 code. Includes:
Patches contributed by Oliver-Rainer Wittmann
    sw34bf06: #i117783# - Writer's implementation of XPagePrintable -
    apply print settings to new printing routines
    http://svn.apache.org/viewvc?view=revision&revision=1172115
    sw34bf06: #o12311627# use <rtl_random> methods to
    create unique ids for list styles and list ids
    http://svn.apache.org/viewvc?view=revision&revision=1172112
    sw34bf06 #i114725#,#i115828# - method <SwDoc::ClearDoc()> -
    clear list structures completely
    http://svn.apache.org/viewvc?view=revision&revision=1172122
    i#118572 - remove ui string and help content regarding usage of
    Java Mail in Writer's Mail Merge as Java Mail is not used.
    http://svn.apache.org/viewvc?view=revision&revision=1197035

    Patches contributed by Mathias Bauer
    cws mba34issues01: #i117718#: provide filter name in
    case storage of medium does not allow to detect one
    http://svn.apache.org/viewvc?view=revision&revision=1172350
    cws mba34issues01: #i117721#: directly provide
    parameters retrieved from SfxMedium
    http://svn.apache.org/viewvc?view=revision&revision=1172353
    gnumake4 work variously
    http://svn.apache.org/viewvc?view=revision&revision=1394707
    http://svn.apache.org/viewvc?view=revision&revision=1394326
    http://svn.apache.org/viewvc?view=revision&revision=1396797
    http://svn.apache.org/viewvc?view=revision&revision=1397315
    cws mba34issues01: #i117723#: convert assertion into trace
    http://svn.apache.org/viewvc?view=revision&revision=1172355
    cws mba34issues01: #i117699#: keep layout alive until swdoc dies
    http://svn.apache.org/viewvc?view=revision&revision=1172362
    cws mba34issues01: #i117943#: missing color attributes in RTF clipboard
    http://svn.apache.org/viewvc?view=revision&revision=1172363

    Patch contributed by Henning Brinkmann
    imported patch i#103878
    http://svn.apache.org/viewvc?view=revision&revision=1172109

    Patches contributed by Michael Stahl
    sw34bf06: #i117955#: WW8 export: disable storing of section breaks in endnotes
    http://svn.apache.org/viewvc?view=revision&revision=1172119

    Patch contributed by imacat
    Fixed the Asian language work count.
    http://svn.apache.org/viewvc?view=revision&revision=1241345

    Patch contributed by Pedro Giffuni
    i#20878 - Add comment with BZ issue for reference.
    http://svn.apache.org/viewvc?view=revision&revision=1244517

    Patch contributed by Andre Fischer
    Do not add targets for junit tests when junit is disabled.
    http://svn.apache.org/viewvc?view=revision&revision=1241508

add writerperfect dependency.
2012-11-30 10:10:38 +00:00

447 lines
16 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* 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 .
*/
#include <ascharanchoredobjectposition.hxx>
#include <frame.hxx>
#include <txtfrm.hxx>
#include <flyfrms.hxx>
#include <svx/svdobj.hxx>
#include <dcontact.hxx>
#include <frmfmt.hxx>
#include <frmatr.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <fmtornt.hxx>
#include <com/sun/star/text/HoriOrientation.hpp>
using namespace ::com::sun::star;
using namespace objectpositioning;
/** constructor
@author OD
*/
SwAsCharAnchoredObjectPosition::SwAsCharAnchoredObjectPosition(
SdrObject& _rDrawObj,
const Point& _rProposedAnchorPos,
const AsCharFlags _nFlags,
const SwTwips _nLineAscent,
const SwTwips _nLineDescent,
const SwTwips _nLineAscentInclObjs,
const SwTwips _nLineDescentInclObjs )
: SwAnchoredObjectPosition( _rDrawObj ),
mrProposedAnchorPos( _rProposedAnchorPos ),
mnFlags( _nFlags ),
mnLineAscent( _nLineAscent ),
mnLineDescent( _nLineDescent ),
mnLineAscentInclObjs( _nLineAscentInclObjs ),
mnLineDescentInclObjs( _nLineDescentInclObjs ),
maAnchorPos ( Point() ),
mnRelPos ( 0 ),
maObjBoundRect ( SwRect() ),
mnLineAlignment ( 0 )
{}
/** destructor
@author OD
*/
SwAsCharAnchoredObjectPosition::~SwAsCharAnchoredObjectPosition()
{}
/** method to cast <SwAnchoredObjectPosition::GetAnchorFrm()> to needed type
@author OD
*/
const SwTxtFrm& SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() const
{
OSL_ENSURE( GetAnchorFrm().ISA(SwTxtFrm),
"SwAsCharAnchoredObjectPosition::GetAnchorTxtFrm() - wrong anchor frame type" );
return static_cast<const SwTxtFrm&>(GetAnchorFrm());
}
/** calculate position for object
OD 30.07.2003 #110978#
members <maAnchorPos>, <mnRelPos>, <maObjBoundRect> and
<mnLineAlignment> are calculated.
calculated position is set at the given object.
@author OD
*/
void SwAsCharAnchoredObjectPosition::CalcPosition()
{
const SwTxtFrm& rAnchorFrm = GetAnchorTxtFrm();
// swap anchor frame, if swapped. Note: destructor takes care of the 'undo'
SwFrmSwapper aFrmSwapper( &rAnchorFrm, false );
SWRECTFN( ( &rAnchorFrm ) )
Point aAnchorPos( mrProposedAnchorPos );
const SwFrmFmt& rFrmFmt = GetFrmFmt();
SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
SwTwips nObjWidth = (aObjBoundRect.*fnRect->fnGetWidth)();
// determine spacing values considering layout-/text-direction
const SvxLRSpaceItem& rLRSpace = rFrmFmt.GetLRSpace();
const SvxULSpaceItem& rULSpace = rFrmFmt.GetULSpace();
SwTwips nLRSpaceLeft, nLRSpaceRight, nULSpaceUpper, nULSpaceLower;
{
if ( rAnchorFrm.IsVertical() )
{
// Seems to be easier to do it all the horizontal way
// So, from now on think horizontal.
rAnchorFrm.SwitchVerticalToHorizontal( aObjBoundRect );
rAnchorFrm.SwitchVerticalToHorizontal( aAnchorPos );
// convert the spacing values
nLRSpaceLeft = rULSpace.GetUpper();
nLRSpaceRight = rULSpace.GetLower();
nULSpaceUpper = rLRSpace.GetRight();
nULSpaceLower = rLRSpace.GetLeft();
}
else
{
if ( rAnchorFrm.IsRightToLeft() )
{
nLRSpaceLeft = rLRSpace.GetRight();
nLRSpaceRight = rLRSpace.GetLeft();
}
else
{
nLRSpaceLeft = rLRSpace.GetLeft();
nLRSpaceRight = rLRSpace.GetRight();
}
nULSpaceUpper = rULSpace.GetUpper();
nULSpaceLower = rULSpace.GetLower();
}
}
// consider left and upper spacing by adjusting anchor position.
// left spacing is only considered, if requested.
if( mnFlags & AS_CHAR_ULSPACE )
{
aAnchorPos.X() += nLRSpaceLeft;
}
aAnchorPos.Y() += nULSpaceUpper;
// for drawing objects: consider difference between its bounding rectangle
// and its snapping rectangle by adjusting anchor position.
// left difference is only considered, if requested.
if( !IsObjFly() )
{
SwRect aSnapRect = GetObject().GetSnapRect();
if ( rAnchorFrm.IsVertical() )
{
rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
}
if( mnFlags & AS_CHAR_ULSPACE )
{
aAnchorPos.X() += aSnapRect.Left() - aObjBoundRect.Left();
}
aAnchorPos.Y() += aSnapRect.Top() - aObjBoundRect.Top();
}
// enlarge bounding rectangle of object by its spacing.
aObjBoundRect.Left( aObjBoundRect.Left() - nLRSpaceLeft );
aObjBoundRect.Width( aObjBoundRect.Width() + nLRSpaceRight );
aObjBoundRect.Top( aObjBoundRect.Top() - nULSpaceUpper );
aObjBoundRect.Height( aObjBoundRect.Height() + nULSpaceLower );
// calculate relative position to given base line.
const SwFmtVertOrient& rVert = rFrmFmt.GetVertOrient();
const SwTwips nObjBoundHeight = ( mnFlags & AS_CHAR_ROTATE )
? aObjBoundRect.Width()
: aObjBoundRect.Height();
const SwTwips nRelPos = _GetRelPosToBase( nObjBoundHeight, rVert );
// for initial positioning:
// adjust the proposed anchor position by difference between
// calculated relative position to base line and current maximal line ascent.
// Note: In the following line formatting the base line will be adjusted
// by the same difference.
if( mnFlags & AS_CHAR_INIT && nRelPos < 0 && mnLineAscentInclObjs < -nRelPos )
{
if( mnFlags & AS_CHAR_ROTATE )
aAnchorPos.X() -= mnLineAscentInclObjs + nRelPos;
else
aAnchorPos.Y() -= mnLineAscentInclObjs + nRelPos;
}
// consider BIDI-multiportion by adjusting proposed anchor position
if( mnFlags & AS_CHAR_BIDI )
aAnchorPos.X() -= aObjBoundRect.Width();
// calculate relative position considering rotation and inside rotation
// reverse direction.
Point aRelPos;
{
if( mnFlags & AS_CHAR_ROTATE )
{
if( mnFlags & AS_CHAR_REVERSE )
aRelPos.X() = -nRelPos - aObjBoundRect.Width();
else
{
aRelPos.X() = nRelPos;
aRelPos.Y() = -aObjBoundRect.Height();
}
}
else
aRelPos.Y() = nRelPos;
}
if( !IsObjFly() )
{
if( !( mnFlags & AS_CHAR_QUICK ) )
{
// save calculated Y-position value for 'automatic' vertical positioning,
// in order to avoid a switch to 'manual' vertical positioning in
// <SwDrawContact::_Changed(..)>.
const sal_Int16 eVertOrient = rVert.GetVertOrient();
if( rVert.GetPos() != nRelPos && eVertOrient != text::VertOrientation::NONE )
{
SwFmtVertOrient aVert( rVert );
aVert.SetPos( nRelPos );
const_cast<SwFrmFmt&>(rFrmFmt).LockModify();
const_cast<SwFrmFmt&>(rFrmFmt).SetFmtAttr( aVert );
const_cast<SwFrmFmt&>(rFrmFmt).UnlockModify();
}
// determine absolute anchor position considering layout directions.
// Note: Use copy of <aAnchorPos>, because it's needed for
// setting relative position.
Point aAbsAnchorPos( aAnchorPos );
if ( rAnchorFrm.IsRightToLeft() )
{
rAnchorFrm.SwitchLTRtoRTL( aAbsAnchorPos );
aAbsAnchorPos.X() -= nObjWidth;
}
if ( rAnchorFrm.IsVertical() )
rAnchorFrm.SwitchHorizontalToVertical( aAbsAnchorPos );
// set proposed anchor position at the drawing object.
// OD 2004-04-06 #i26791# - distinction between 'master' drawing
// object and 'virtual' drawing object no longer needed.
GetObject().SetAnchorPos( aAbsAnchorPos );
// move drawing object to set its correct relative position.
{
SwRect aSnapRect = GetObject().GetSnapRect();
if ( rAnchorFrm.IsVertical() )
rAnchorFrm.SwitchVerticalToHorizontal( aSnapRect );
Point aDiff;
if ( rAnchorFrm.IsRightToLeft() )
aDiff = aRelPos + aAbsAnchorPos - aSnapRect.TopLeft();
else
aDiff = aRelPos + aAnchorPos - aSnapRect.TopLeft();
if ( rAnchorFrm.IsVertical() )
aDiff = Point( -aDiff.Y(), aDiff.X() );
// OD 2004-04-06 #i26791# - distinction between 'master' drawing
// object and 'virtual' drawing object no longer needed.
GetObject().Move( Size( aDiff.X(), aDiff.Y() ) );
}
}
// switch horizontal, LTR anchor position to absolute values.
if ( rAnchorFrm.IsRightToLeft() )
{
rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
aAnchorPos.X() -= nObjWidth;
}
if ( rAnchorFrm.IsVertical() )
rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
// #i44347# - keep last object rectangle at anchored object
OSL_ENSURE( GetAnchoredObj().ISA(SwAnchoredDrawObject),
"<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong type of anchored object." );
SwAnchoredDrawObject& rAnchoredDrawObj =
static_cast<SwAnchoredDrawObject&>( GetAnchoredObj() );
rAnchoredDrawObj.SetLastObjRect( rAnchoredDrawObj.GetObjRect().SVRect() );
}
else
{
// determine absolute anchor position and calculate corresponding
// relative position and its relative position attribute.
// Note: The relative position contains the spacing values.
Point aRelAttr;
if ( rAnchorFrm.IsRightToLeft() )
{
rAnchorFrm.SwitchLTRtoRTL( aAnchorPos );
aAnchorPos.X() -= nObjWidth;
}
if ( rAnchorFrm.IsVertical() )
{
rAnchorFrm.SwitchHorizontalToVertical( aAnchorPos );
aRelAttr = Point( -nRelPos, 0 );
aRelPos = Point( -aRelPos.Y(), aRelPos.X() );
}
else
aRelAttr = Point( 0, nRelPos );
// OD 2004-03-23 #i26791#
OSL_ENSURE( GetAnchoredObj().ISA(SwFlyInCntFrm),
"<SwAsCharAnchoredObjectPosition::CalcPosition()> - wrong anchored object." );
const SwFlyInCntFrm& rFlyInCntFrm =
static_cast<const SwFlyInCntFrm&>(GetAnchoredObj());
if ( !(mnFlags & AS_CHAR_QUICK) &&
( aAnchorPos != rFlyInCntFrm.GetRefPoint() ||
aRelAttr != rFlyInCntFrm.GetCurrRelPos() ) )
{
// set new anchor position and relative position
SwFlyInCntFrm* pFlyInCntFrm = &(const_cast<SwFlyInCntFrm&>(rFlyInCntFrm));
pFlyInCntFrm->SetRefPoint( aAnchorPos, aRelAttr, aRelPos );
if( nObjWidth != (pFlyInCntFrm->Frm().*fnRect->fnGetWidth)() )
{
// recalculate object bound rectangle, if object width has changed.
aObjBoundRect = GetAnchoredObj().GetObjRect();
aObjBoundRect.Left( aObjBoundRect.Left() - rLRSpace.GetLeft() );
aObjBoundRect.Width( aObjBoundRect.Width() + rLRSpace.GetRight() );
aObjBoundRect.Top( aObjBoundRect.Top() - rULSpace.GetUpper() );
aObjBoundRect.Height( aObjBoundRect.Height() + rULSpace.GetLower() );
}
}
OSL_ENSURE( (rFlyInCntFrm.Frm().*fnRect->fnGetHeight)(),
"SwAnchoredObjectPosition::CalcPosition(..) - fly frame has an invalid height" );
}
// keep calculated values
maAnchorPos = aAnchorPos;
mnRelPos = nRelPos;
maObjBoundRect = aObjBoundRect;
}
/** determine the relative position to base line for object position type AS_CHAR
OD 29.07.2003 #110978#
Note about values set at member <mnLineAlignment> -
value gives feedback for the line formatting.
0 - no feedback; 1|2|3 - proposed formatting of characters
at top|at center|at bottom of line.
@author OD
*/
SwTwips SwAsCharAnchoredObjectPosition::_GetRelPosToBase(
const SwTwips _nObjBoundHeight,
const SwFmtVertOrient& _rVert )
{
SwTwips nRelPosToBase = 0;
mnLineAlignment = 0;
const sal_Int16 eVertOrient = _rVert.GetVertOrient();
if ( eVertOrient == text::VertOrientation::NONE )
nRelPosToBase = _rVert.GetPos();
else
{
if ( eVertOrient == text::VertOrientation::CENTER )
nRelPosToBase -= _nObjBoundHeight / 2;
else if ( eVertOrient == text::VertOrientation::TOP )
nRelPosToBase -= _nObjBoundHeight;
else if ( eVertOrient == text::VertOrientation::BOTTOM )
nRelPosToBase = 0;
else if ( eVertOrient == text::VertOrientation::CHAR_CENTER )
nRelPosToBase -= ( _nObjBoundHeight + mnLineAscent - mnLineDescent ) / 2;
else if ( eVertOrient == text::VertOrientation::CHAR_TOP )
nRelPosToBase -= mnLineAscent;
else if ( eVertOrient == text::VertOrientation::CHAR_BOTTOM )
nRelPosToBase += mnLineDescent - _nObjBoundHeight;
else
{
if( _nObjBoundHeight >= mnLineAscentInclObjs + mnLineDescentInclObjs )
{
// object is at least as high as the line. Thus, no more is
// positioning necessary. Also, the max. ascent isn't changed.
nRelPosToBase -= mnLineAscentInclObjs;
if ( eVertOrient == text::VertOrientation::LINE_CENTER )
mnLineAlignment = 2;
else if ( eVertOrient == text::VertOrientation::LINE_TOP )
mnLineAlignment = 1;
else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
mnLineAlignment = 3;
}
else if ( eVertOrient == text::VertOrientation::LINE_CENTER )
{
nRelPosToBase -= ( _nObjBoundHeight + mnLineAscentInclObjs - mnLineDescentInclObjs ) / 2;
mnLineAlignment = 2;
}
else if ( eVertOrient == text::VertOrientation::LINE_TOP )
{
nRelPosToBase -= mnLineAscentInclObjs;
mnLineAlignment = 1;
}
else if ( eVertOrient == text::VertOrientation::LINE_BOTTOM )
{
nRelPosToBase += mnLineDescentInclObjs - _nObjBoundHeight;
mnLineAlignment = 3;
}
}
}
return nRelPosToBase;
}
/** calculated anchored position for object position
@author OD
*/
Point SwAsCharAnchoredObjectPosition::GetAnchorPos() const
{
return maAnchorPos;
}
/** calculated relative position to base line for object position
@author OD
*/
SwTwips SwAsCharAnchoredObjectPosition::GetRelPosY() const
{
return mnRelPos;
}
/** determined object rectangle including spacing for object
@author OD
*/
SwRect SwAsCharAnchoredObjectPosition::GetObjBoundRectInclSpacing() const
{
return maObjBoundRect;
}
/** determined line alignment
@author OD
*/
sal_uInt8 SwAsCharAnchoredObjectPosition::GetLineAlignment() const
{
return mnLineAlignment;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */