fit-list-to-size.diff: Shrink font automatically when text overflows.

i#94086

Scale-font-down if typing text in Impress and the text box becomes too small.
This commit is contained in:
Thorsten Behrens 2010-09-17 10:11:31 +02:00 committed by Jan Holesovsky
parent 1ea6792208
commit e479f47f7d
21 changed files with 456 additions and 92 deletions

View file

@ -112,12 +112,16 @@ class XParaPortionList : public XBaseParaPortionList
ULONG nRefDevPtr;
OutDevType eRefDevType;
MapMode aRefMapMode;
sal_uInt16 nStretchX;
sal_uInt16 nStretchY;
ULONG nPaperWidth;
public:
XParaPortionList( OutputDevice* pRefDev, ULONG nPW ) :
aRefMapMode( pRefDev->GetMapMode() )
XParaPortionList( OutputDevice* pRefDev, ULONG nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY ) :
aRefMapMode( pRefDev->GetMapMode() ),
nStretchX(_nStretchX),
nStretchY(_nStretchY)
{
nRefDevPtr = (ULONG)pRefDev; nPaperWidth = nPW;
eRefDevType = pRefDev->GetOutDevType();
@ -127,6 +131,8 @@ public:
ULONG GetPaperWidth() const { return nPaperWidth; }
OutDevType GetRefDevType() const { return eRefDevType; }
const MapMode& GetRefMapMode() const { return aRefMapMode; }
sal_uInt16 GetStretchX() const { return nStretchX; }
sal_uInt16 GetStretchY() const { return nStretchY; }
};
/* cl removed because not needed anymore since binfilter

View file

@ -2657,36 +2657,44 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_uInt16 nPos, SvxFont& rF
}
if ( nStretchX != 100 )
{
aRealSz.Width() *= nStretchX;
aRealSz.Width() /= 100;
if ( nStretchX == nStretchY &&
nRelWidth == 100 )
{
aRealSz.Width() = 0;
}
else
{
aRealSz.Width() *= nStretchX;
aRealSz.Width() /= 100;
// Auch das Kerning: (long wegen Zwischenergebnis)
long nKerning = rFont.GetFixKerning();
// Auch das Kerning: (long wegen Zwischenergebnis)
long nKerning = rFont.GetFixKerning();
/*
Die Ueberlegung war: Wenn neg. Kerning, aber StretchX = 200
=> Nicht das Kerning verdoppelt, also die Buchstaben weiter
zusammenziehen
---------------------------
Kern StretchX =>Kern
---------------------------
>0 <100 < (Proportional)
<0 <100 < (Proportional)
>0 >100 > (Proportional)
<0 >100 < (Der Betrag, also Antiprop)
Die Ueberlegung war: Wenn neg. Kerning, aber StretchX = 200
=> Nicht das Kerning verdoppelt, also die Buchstaben weiter
zusammenziehen
---------------------------
Kern StretchX =>Kern
---------------------------
>0 <100 < (Proportional)
<0 <100 < (Proportional)
>0 >100 > (Proportional)
<0 >100 < (Der Betrag, also Antiprop)
*/
if ( ( nKerning < 0 ) && ( nStretchX > 100 ) )
{
// Antiproportional
nKerning *= 100;
nKerning /= nStretchX;
if ( ( nKerning < 0 ) && ( nStretchX > 100 ) )
{
// Antiproportional
nKerning *= 100;
nKerning /= nStretchX;
}
else if ( nKerning )
{
// Proportional
nKerning *= nStretchX;
nKerning /= 100;
}
rFont.SetFixKerning( (short)nKerning );
}
else if ( nKerning )
{
// Proportional
nKerning *= nStretchX;
nKerning /= 100;
}
rFont.SetFixKerning( (short)nKerning );
}
}
if ( nRelWidth != 100 )
@ -4095,20 +4103,25 @@ void ImpEditEngine::SetFlatMode( sal_Bool bFlat )
void ImpEditEngine::SetCharStretching( sal_uInt16 nX, sal_uInt16 nY )
{
bool bChanged(false);
if ( !IsVertical() )
{
bChanged = nStretchX!=nX || nStretchY!=nY;
nStretchX = nX;
nStretchY = nY;
}
else
{
bChanged = nStretchX!=nY || nStretchY!=nX;
nStretchX = nY;
nStretchY = nX;
}
if ( aStatus.DoStretch() )
if (bChanged && aStatus.DoStretch())
{
FormatFullDoc();
// (potentially) need everything redrawn
aInvalidRec=Rectangle(0,0,1000000,1000000);
UpdateViews( GetActiveView() );
}
}

View file

@ -1159,7 +1159,7 @@ EditTextObject* ImpEditEngine::CreateBinTextObject( EditSelection aSel, SfxItemP
// Schwelle rauf setzen, wenn Olli die Absaetze nicht mehr zerhackt!
if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && GetUpdateMode() && ( nTextPortions >= nBigObjectStart ) )
{
XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), aPaperSize.Width() );
XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), aPaperSize.Width(), nStretchX, nStretchY );
pTxtObj->SetPortionInfo( pXList );
for ( nNode = nStartNode; nNode <= nEndNode; nNode++ )
{
@ -1250,7 +1250,9 @@ EditSelection ImpEditEngine::InsertBinTextObject( BinTextObject& rTextObject, Ed
XParaPortionList* pPortionInfo = rTextObject.GetPortionInfo();
if ( pPortionInfo && ( (long)pPortionInfo->GetPaperWidth() == aPaperSize.Width() )
&& ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() ) )
&& ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() )
&& ( pPortionInfo->GetStretchX() == nStretchX )
&& ( pPortionInfo->GetStretchY() == nStretchY ) )
{
if ( ( pPortionInfo->GetRefDevPtr() == (sal_uIntPtr)GetRefDevice() ) ||
( ( pPortionInfo->GetRefDevType() == OUTDEV_VIRDEV ) &&

View file

@ -925,7 +925,10 @@ Font Outliner::ImpCalcBulletFont( USHORT nPara ) const
}
// #107508# Use original scale...
USHORT nScale = /* pEditEngine->IsFlatMode() ? DEFAULT_SCALE : */ pFmt->GetBulletRelSize();
USHORT nStretchX, nStretchY;
const_cast<Outliner*>(this)->GetGlobalCharStretching(nStretchX, nStretchY);
USHORT nScale = pFmt->GetBulletRelSize() * nStretchY / 100;
ULONG nScaledLineHeight = aStdFont.GetSize().Height();
nScaledLineHeight *= nScale*10;
nScaledLineHeight /= 1000;
@ -968,6 +971,12 @@ void Outliner::PaintBullet( USHORT nPara, const Point& rStartPos,
BOOL bRightToLeftPara = pEditEngine->IsRightToLeft( nPara );
Rectangle aBulletArea( ImpCalcBulletArea( nPara, TRUE, FALSE ) );
USHORT nStretchX, nStretchY;
GetGlobalCharStretching(nStretchX, nStretchY);
aBulletArea = Rectangle( Point(aBulletArea.Left()*nStretchX/100,
aBulletArea.Top()),
Size(aBulletArea.GetWidth()*nStretchX/100,
aBulletArea.GetHeight()) );
Paragraph* pPara = pParaList->GetParagraph( nPara );
const SvxNumberFormat* pFmt = GetNumberFormat( nPara );

View file

@ -75,6 +75,7 @@ namespace drawinglayer
SdrTextVertAdjust aSdrTextVertAdjust,
bool bContour,
bool bFitToSize,
bool bAutoFit,
bool bHideContour,
bool bBlink,
bool bScroll,
@ -97,6 +98,7 @@ namespace drawinglayer
const OutlinerParaObject& getOutlinerParaObject() const;
bool isContour() const;
bool isFitToSize() const;
bool isAutoFit() const;
bool isHideContour() const;
bool isBlink() const;
bool isScroll() const;

View file

@ -300,6 +300,47 @@ namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace primitive2d
{
class SdrAutoFitTextPrimitive2D : public SdrTextPrimitive2D
{
private:
::basegfx::B2DHomMatrix maTextRangeTransform; // text range transformation from unit range ([0.0 .. 1.0]) to text range
// bitfield
unsigned mbWordWrap : 1; // for CustomShapes text layout
protected:
// local decomposition.
virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const;
public:
SdrAutoFitTextPrimitive2D(
const SdrText* pSdrText,
const OutlinerParaObject& rOutlinerParaObjectPtr,
const ::basegfx::B2DHomMatrix& rTextRangeTransform,
bool bWordWrap);
// get data
const basegfx::B2DHomMatrix& getTextRangeTransform() const { return maTextRangeTransform; }
bool getWordWrap() const { return mbWordWrap; }
// compare operator
virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
// transformed clone operator
virtual SdrTextPrimitive2D* createTransformedClone(const ::basegfx::B2DHomMatrix& rTransform) const;
// provide unique ID
DeclPrimitrive2DIDBlock()
};
} // end of namespace primitive2d
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
#endif //INCLUDED_SDR_PRIMITIVE2D_SDRTEXTPRIMITIVE2D_HXX
// eof

View file

@ -55,6 +55,7 @@
#define PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE (PRIMITIVE2D_ID_RANGE_SVX| 20)
#define PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 21)
#define PRIMITIVE2D_ID_SDROLECONTENTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 22)
#define PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D (PRIMITIVE2D_ID_RANGE_SVX| 23)
//////////////////////////////////////////////////////////////////////////////

View file

@ -31,19 +31,21 @@
#include <svx/svddef.hxx>
#include "svx/svxdllapi.h"
enum SdrFitToSizeType {SDRTEXTFIT_NONE, // - kein FitToSize
SDRTEXTFIT_PROPORTIONAL, // - Alle Buchstaben proportional umgroessern
SDRTEXTFIT_ALLLINES, // - Zus. jede Zeile separat in der Breite stretchen
SDRTEXTFIT_RESIZEATTR}; // - Bei Rahmenumgroesserung (ausser Autogrow) wird
// die Schriftgroesse umattributiert (hart)
enum SdrFitToSizeType {
SDRTEXTFIT_NONE, // - no fit-to-size
SDRTEXTFIT_PROPORTIONAL, // - resize all glyhs proportionally
// (might scale anisotrophically)
SDRTEXTFIT_ALLLINES, // - like SDRTEXTFIT_PROPORTIONAL, but
// scales each line separately
SDRTEXTFIT_AUTOFIT}; // - mimics PPT's automatic adaption of
// font size to text rect - comparable
// to SDRTEXTFIT_PROPORTIONAL, but
// scales isotrophically
// Bei SDRTEXTFIT_PROPORTIONAL und SDRTEXTFIT_ALLLINES gibt es kein AutoGrow und
// keine automatischen Umbrueche.
// Ist SDRTEXTFIT_RESIZEATTR gesetzt, so wird beim umgroessern des Textrahmens
// (ausser bei AutoGrow) die Schrift durch harte Attributierung ebenfalls
// umgegroessert.
// Bei AutoGrowingWidth gibt es ebenfalls keine automatischen Umbrueche (erst bei
// TextMaxFrameWidth).
// No AutoGrow and no automatic line breaks for
// SDRTEXTFIT_PROPORTIONAL and SDRTEXTFIT_ALLLINES.
// No automatic line breaks for AutoGrowingWidth as well (only if
// TextMaxFrameWidth is reached).
//--------------------------------
// class SdrTextFitToSizeTypeItem

View file

@ -59,6 +59,7 @@ namespace drawinglayer { namespace primitive2d {
class SdrContourTextPrimitive2D;
class SdrPathTextPrimitive2D;
class SdrBlockTextPrimitive2D;
class SdrAutoFitTextPrimitive2D;
class SdrStretchTextPrimitive2D;
}}
@ -254,6 +255,9 @@ protected:
// Flag for allowing text animation. Default is sal_true.
BOOL mbTextAnimationAllowed : 1;
// flag for preventing recursive onEditOutlinerStatusEvent calls
BOOL mbInDownScale : 1;
SdrOutliner& ImpGetDrawOutliner() const;
private:
@ -267,6 +271,8 @@ private:
Rectangle& rAnchorRect,
Rectangle& rPaintRect,
Fraction& aFitXKorreg ) const;
void ImpAutoFitText( SdrOutliner& rOutliner ) const;
static void ImpAutoFitText( SdrOutliner& rOutliner, const Size& rShapeSize, bool bIsVerticalWriting );
SVX_DLLPRIVATE SdrObject* ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const;
SVX_DLLPRIVATE void ImpLinkAnmeldung();
SVX_DLLPRIVATE void ImpLinkAbmeldung();
@ -278,7 +284,7 @@ protected:
SdrObject* ImpConvertMakeObj(const basegfx::B2DPolyPolygon& rPolyPolygon, sal_Bool bClosed, sal_Bool bBezier, sal_Bool bNoSetAttr = sal_False) const;
SdrObject* ImpConvertAddText(SdrObject* pObj, FASTBOOL bBezier) const;
void ImpSetTextStyleSheetListeners();
void ImpSetCharStretching(SdrOutliner& rOutliner, const Rectangle& rTextRect, const Rectangle& rAnchorRect, Fraction& rFitXKorreg) const;
void ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg) const;
void ImpJustifyRect(Rectangle& rRect) const;
void ImpCheckShear();
Rectangle ImpDragCalcRect(const SdrDragStat& rDrag) const;
@ -340,6 +346,10 @@ public:
void NbcResizeTextAttributes(const Fraction& xFact, const Fraction& yFact);
FASTBOOL IsTextFrame() const { return bTextFrame; }
FASTBOOL IsOutlText() const { return bTextFrame && (eTextKind==OBJ_OUTLINETEXT || eTextKind==OBJ_TITLETEXT); }
/// returns true if the PPT autofit of text into shape bounds is enabled. implies IsFitToSize()==false!
FASTBOOL IsAutoFit() const;
/// returns true if the old feature for fitting shape content should into shape is enabled. implies IsAutoFit()==false!
FASTBOOL IsFitToSize() const;
SdrObjKind GetTextKind() const { return eTextKind; }
virtual bool HasText() const;
@ -582,6 +592,10 @@ public:
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::SdrBlockTextPrimitive2D& rSdrBlockTextPrimitive,
const drawinglayer::geometry::ViewInformation2D& aViewInformation) const;
void impDecomposeAutoFitTextPrimitive(
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::SdrAutoFitTextPrimitive2D& rSdrAutofitTextPrimitive,
const drawinglayer::geometry::ViewInformation2D& aViewInformation) const;
void impDecomposeStretchTextPrimitive(
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::SdrStretchTextPrimitive2D& rSdrStretchTextPrimitive,

View file

@ -71,6 +71,7 @@ namespace drawinglayer
// bitfield
unsigned mbContour : 1;
unsigned mbFitToSize : 1;
unsigned mbAutoFit : 1;
unsigned mbHideContour : 1;
unsigned mbBlink : 1;
unsigned mbScroll : 1;
@ -91,6 +92,7 @@ namespace drawinglayer
SdrTextVertAdjust aSdrTextVertAdjust,
bool bContour,
bool bFitToSize,
bool bAutoFit,
bool bHideContour,
bool bBlink,
bool bScroll,
@ -110,6 +112,7 @@ namespace drawinglayer
maSdrTextVertAdjust(aSdrTextVertAdjust),
mbContour(bContour),
mbFitToSize(bFitToSize),
mbAutoFit(bAutoFit),
mbHideContour(bHideContour),
mbBlink(bBlink),
mbScroll(bScroll),
@ -147,6 +150,7 @@ namespace drawinglayer
maSdrTextVertAdjust(SDRTEXTVERTADJUST_TOP),
mbContour(false),
mbFitToSize(false),
mbAutoFit(false),
mbHideContour(false),
mbBlink(false),
mbScroll(false),
@ -177,6 +181,7 @@ namespace drawinglayer
}
bool isContour() const { return mbContour; }
bool isFitToSize() const { return mbFitToSize; }
bool isAutoFit() const { return mbAutoFit; }
bool isHideContour() const { return mbHideContour; }
bool isBlink() const { return mbBlink; }
bool isScroll() const { return mbScroll; }
@ -235,6 +240,7 @@ namespace drawinglayer
&& isContour() == rCandidate.isContour()
&& isFitToSize() == rCandidate.isFitToSize()
&& isAutoFit() == rCandidate.isAutoFit()
&& isHideContour() == rCandidate.isHideContour()
&& isBlink() == rCandidate.isBlink()
&& isScroll() == rCandidate.isScroll()
@ -272,6 +278,7 @@ namespace drawinglayer
SdrTextVertAdjust aSdrTextVertAdjust,
bool bContour,
bool bFitToSize,
bool bAutoFit,
bool bHideContour,
bool bBlink,
bool bScroll,
@ -281,7 +288,7 @@ namespace drawinglayer
: mpSdrTextAttribute(new ImpSdrTextAttribute(
&rSdrText, rOutlinerParaObject, eFormTextStyle, aTextLeftDistance, aTextUpperDistance,
aTextRightDistance, aTextLowerDistance, aSdrTextHorzAdjust, aSdrTextVertAdjust, bContour,
bFitToSize, bHideContour, bBlink, bScroll, bInEditMode, bFixedCellHeight, bWrongSpell))
bFitToSize, bAutoFit, bHideContour, bBlink, bScroll, bInEditMode, bFixedCellHeight, bWrongSpell))
{
}
@ -369,6 +376,11 @@ namespace drawinglayer
return mpSdrTextAttribute->isFitToSize();
}
bool SdrTextAttribute::isAutoFit() const
{
return mpSdrTextAttribute->isAutoFit();
}
bool SdrTextAttribute::isHideContour() const
{
return mpSdrTextAttribute->isHideContour();

View file

@ -544,7 +544,8 @@ namespace drawinglayer
rTextObj.GetTextHorizontalAdjust(rSet),
rTextObj.GetTextVerticalAdjust(rSet),
((const SdrTextContourFrameItem&)rSet.Get(SDRATTR_TEXT_CONTOURFRAME)).GetValue(),
(SDRTEXTFIT_PROPORTIONAL == eFit || SDRTEXTFIT_ALLLINES == eFit),
rTextObj.IsFitToSize(),
rTextObj.IsAutoFit(),
((const XFormTextHideFormItem&)rSet.Get(XATTR_FORMTXTHIDEFORM)).GetValue(),
SDRTEXTANI_BLINK == eAniKind,
SDRTEXTANI_SCROLL == eAniKind || SDRTEXTANI_ALTERNATE == eAniKind || SDRTEXTANI_SLIDE == eAniKind,

View file

@ -281,6 +281,11 @@ namespace drawinglayer
aAnchorTransform,
rText.isFixedCellHeight());
}
else if(rText.isAutoFit())
{
// isotrophically scaled text in range
pNew = new SdrAutoFitTextPrimitive2D(&rText.getSdrText(), rText.getOutlinerParaObject(), aAnchorTransform, bWordWrap);
}
else // text in range
{
// build new primitive

View file

@ -446,6 +446,55 @@ namespace drawinglayer
{
namespace primitive2d
{
Primitive2DSequence SdrAutoFitTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
{
Primitive2DSequence aRetval;
getSdrText()->GetObject().impDecomposeAutoFitTextPrimitive(aRetval, *this, aViewInformation);
return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval);
}
SdrAutoFitTextPrimitive2D::SdrAutoFitTextPrimitive2D(
const SdrText* pSdrText,
const OutlinerParaObject& rParaObj,
const ::basegfx::B2DHomMatrix& rTextRangeTransform,
bool bWordWrap)
: SdrTextPrimitive2D(pSdrText, rParaObj),
maTextRangeTransform(rTextRangeTransform),
mbWordWrap(bWordWrap)
{
}
bool SdrAutoFitTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
{
if(SdrTextPrimitive2D::operator==(rPrimitive))
{
const SdrBlockTextPrimitive2D& rCompare = (SdrBlockTextPrimitive2D&)rPrimitive;
return (getTextRangeTransform() == rCompare.getTextRangeTransform()
&& getWordWrap() == rCompare.getWordWrap());
}
return false;
}
SdrTextPrimitive2D* SdrAutoFitTextPrimitive2D::createTransformedClone(const ::basegfx::B2DHomMatrix& rTransform) const
{
return new SdrAutoFitTextPrimitive2D(getSdrText(), getOutlinerParaObject(), rTransform * getTextRangeTransform(), getWordWrap());
}
// provide unique ID
ImplPrimitrive2DIDBlock(SdrAutoFitTextPrimitive2D, PRIMITIVE2D_ID_SDRAUTOFITTEXTPRIMITIVE2D)
} // end of namespace primitive2d
} // end of namespace drawinglayer
//////////////////////////////////////////////////////////////////////////////
namespace drawinglayer
{
namespace primitive2d
{
Primitive2DSequence SdrStretchTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
{
Primitive2DSequence aRetval;

View file

@ -316,7 +316,7 @@ void SdrObjEditView::ImpPaintOutlinerView(OutlinerView& rOutlView, const Rectang
{
const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject());
bool bTextFrame(pText && pText->IsTextFrame());
bool bFitToSize(0 != (pTextEditOutliner->GetControlWord() & EE_CNTRL_STRETCHING));
bool bFitToSize(pText && pText->IsFitToSize());
bool bModifyMerk(pTextEditOutliner->IsModified()); // #43095#
Rectangle aBlankRect(rOutlView.GetOutputArea());
aBlankRect.Union(aMinTextEditArea);
@ -385,7 +385,7 @@ void SdrObjEditView::ImpInvalidateOutlinerView(OutlinerView& rOutlView) const
{
const SdrTextObj* pText = PTR_CAST(SdrTextObj,GetTextEditObject());
bool bTextFrame(pText && pText->IsTextFrame());
bool bFitToSize(0 != (pTextEditOutliner->GetControlWord() & EE_CNTRL_STRETCHING));
bool bFitToSize(pText && pText->IsFitToSize());
if(bTextFrame && !bFitToSize)
{
@ -650,8 +650,7 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit(
if ( !pTextObj->IsContourTextFrame() )
{
// FitToSize erstmal nicht mit ContourFrame
SdrFitToSizeType eFit = pTextObj->GetFitToSize();
if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES)
if (pTextObj->IsFitToSize())
aTextRect = aAnchorRect;
}
@ -719,8 +718,7 @@ sal_Bool SdrObjEditView::SdrBeginTextEdit(
// #71519#
if(!bExtraInvalidate)
{
SdrFitToSizeType eFit = pTextObj->GetFitToSize();
if(eFit == SDRTEXTFIT_PROPORTIONAL || eFit == SDRTEXTFIT_ALLLINES)
if(pTextObj->IsFitToSize())
bExtraInvalidate = sal_True;
}

View file

@ -137,6 +137,7 @@ SdrTextObj::SdrTextObj()
// #i25616#
mbSupportTextIndentingOnLineWidthChange = sal_True;
mbInDownScale = sal_False;
}
SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
@ -162,6 +163,7 @@ SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
// #111096#
mbTextAnimationAllowed = sal_True;
mbInDownScale = sal_False;
// #108784#
maTextEditOffset = Point(0, 0);
@ -192,6 +194,7 @@ SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind)
// #111096#
mbTextAnimationAllowed = sal_True;
mbInDownScale = sal_False;
// #108784#
maTextEditOffset = Point(0, 0);
@ -224,6 +227,7 @@ SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect)
// #111096#
mbTextAnimationAllowed = sal_True;
mbInDownScale = sal_False;
// #108784#
maTextEditOffset = Point(0, 0);
@ -258,6 +262,7 @@ SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStr
// #111096#
mbTextAnimationAllowed = sal_True;
mbInDownScale = sal_False;
// #108784#
maTextEditOffset = Point(0, 0);
@ -834,8 +839,7 @@ void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FAS
SdrTextAniKind eAniKind=GetTextAniKind();
SdrTextAniDirection eAniDirection=GetTextAniDirection();
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bFitToSize(IsFitToSize());
FASTBOOL bContourFrame=IsContourTextFrame();
FASTBOOL bFrame=IsTextFrame();
@ -996,7 +1000,7 @@ OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const
return pPara;
}
void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Rectangle& rTextRect, const Rectangle& rAnchorRect, Fraction& rFitXKorreg) const
void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg) const
{
OutputDevice* pOut = rOutliner.GetRefDevice();
BOOL bNoStretching(FALSE);
@ -1041,12 +1045,12 @@ void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Rectangle& r
unsigned nLoopCount=0;
FASTBOOL bNoMoreLoop=FALSE;
long nXDiff0=0x7FFFFFFF;
long nWantWdt=rAnchorRect.Right()-rAnchorRect.Left();
long nIsWdt=rTextRect.Right()-rTextRect.Left();
long nWantWdt=rShapeSize.Width();
long nIsWdt=rTextSize.Width();
if (nIsWdt==0) nIsWdt=1;
long nWantHgt=rAnchorRect.Bottom()-rAnchorRect.Top();
long nIsHgt=rTextRect.Bottom()-rTextRect.Top();
long nWantHgt=rShapeSize.Height();
long nIsHgt=rTextSize.Height();
if (nIsHgt==0) nIsHgt=1;
long nXTolPl=nWantWdt/100; // Toleranz +1%
@ -1274,8 +1278,7 @@ basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const
Rectangle aR;
TakeTextRect(rOutliner,aR,FALSE,&aAnchor2);
rOutliner.Clear();
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bFitToSize(IsFitToSize());
if (bFitToSize) aR=aAnchor2;
Polygon aPol(aR);
if (aGeo.nDrehWink!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos);
@ -1392,8 +1395,7 @@ void SdrTextObj::ImpSetupDrawOutlinerForPaint( FASTBOOL bContourFrame,
if (!bContourFrame)
{
// FitToSize erstmal nicht mit ContourFrame
SdrFitToSizeType eFit=GetFitToSize();
if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES)
if (IsFitToSize() || IsAutoFit())
{
ULONG nStat=rOutliner.GetControlWord();
nStat|=EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE;
@ -1407,15 +1409,75 @@ void SdrTextObj::ImpSetupDrawOutlinerForPaint( FASTBOOL bContourFrame,
if (!bContourFrame)
{
// FitToSize erstmal nicht mit ContourFrame
SdrFitToSizeType eFit=GetFitToSize();
if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES)
if (IsFitToSize())
{
ImpSetCharStretching(rOutliner,rTextRect,rAnchorRect,rFitXKorreg);
ImpSetCharStretching(rOutliner,rTextRect.GetSize(),rAnchorRect.GetSize(),rFitXKorreg);
rPaintRect=rAnchorRect;
}
else if (IsAutoFit())
{
ImpAutoFitText(rOutliner);
}
}
}
void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
{
const Size aShapeSize=GetSnapRect().GetSize();
ImpAutoFitText( rOutliner,
Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
IsVerticalWriting() );
}
void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
{
// EditEngine formatting is unstable enough for
// line-breaking text that we need some more samples
// loop early-exits if we detect an already attained value
USHORT nMinStretchX=0, nMinStretchY=0;
USHORT aOldStretchXVals[]={0,0,0,0,0,0,0,0,0,0};
const size_t aStretchArySize=sizeof(aOldStretchXVals)/sizeof(*aOldStretchXVals);
for(int i=0; i<aStretchArySize; ++i)
{
const Size aCurrTextSize = rOutliner.CalcTextSize();
double fFactor(1.0);
if( bIsVerticalWriting )
fFactor = double(rTextSize.Width())/aCurrTextSize.Width();
else
fFactor = double(rTextSize.Height())/aCurrTextSize.Height();
USHORT nCurrStretchX, nCurrStretchY;
rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY);
if (fFactor >= 1.0 )
{
// resulting text area fits into available shape rect -
// err on the larger streching, to optimally fill area
nMinStretchX = std::max(nMinStretchX,nCurrStretchX);
nMinStretchY = std::max(nMinStretchY,nCurrStretchY);
}
aOldStretchXVals[i] = nCurrStretchX;
if( std::find(aOldStretchXVals, aOldStretchXVals+i, nCurrStretchX) != aOldStretchXVals+i )
break; // same value already attained once; algo is looping, exit
if (fFactor < 1.0 || (fFactor >= 1.0 && nCurrStretchX != 100))
{
nCurrStretchX = sal::static_int_cast<USHORT>(nCurrStretchX*fFactor);
nCurrStretchY = sal::static_int_cast<USHORT>(nCurrStretchY*fFactor);
rOutliner.SetGlobalCharStretching(std::min(USHORT(100),nCurrStretchX),
std::min(USHORT(100),nCurrStretchY));
OSL_TRACE("SdrTextObj::onEditOutlinerStatusEvent(): zoom is %d", nCurrStretchX);
}
}
OSL_TRACE("---- SdrTextObj::onEditOutlinerStatusEvent(): final zoom is %d ----", nMinStretchX);
rOutliner.SetGlobalCharStretching(std::min(USHORT(100),nMinStretchX),
std::min(USHORT(100),nMinStretchY));
}
void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
{
ImpInitDrawOutliner( rOutl );
@ -1992,6 +2054,17 @@ bool SdrTextObj::IsTextAnimationAllowed() const
return mbTextAnimationAllowed;
}
FASTBOOL SdrTextObj::IsAutoFit() const
{
return GetFitToSize()==SDRTEXTFIT_AUTOFIT;
}
FASTBOOL SdrTextObj::IsFitToSize() const
{
const SdrFitToSizeType eFit=GetFitToSize();
return (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
}
void SdrTextObj::SetTextAnimationAllowed(sal_Bool bNew)
{
if(mbTextAnimationAllowed != bNew)
@ -2009,13 +2082,21 @@ void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
const bool bGrowY=(nStat & EE_STAT_TEXTHEIGHTCHANGED) !=0;
if(bTextFrame && (bGrowX || bGrowY))
{
const bool bAutoGrowHgt= bTextFrame && IsAutoGrowHeight();
const bool bAutoGrowWdt= bTextFrame && IsAutoGrowWidth();
if ((bGrowX && bAutoGrowWdt) || (bGrowY && bAutoGrowHgt))
if ((bGrowX && IsAutoGrowWidth()) || (bGrowY && IsAutoGrowHeight()))
{
AdjustTextFrameWidthAndHeight();
}
else if (IsAutoFit() && !mbInDownScale)
{
OSL_ASSERT(pEdtOutl);
mbInDownScale = sal_True;
// sucks that we cannot disable paints via
// pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
// formatting as well, then.
ImpAutoFitText(*pEdtOutl);
mbInDownScale = sal_False;
}
}
}

View file

@ -729,6 +729,140 @@ void SdrTextObj::impDecomposeContourTextPrimitive(
rTarget = aConverter.getPrimitive2DSequence();
}
void SdrTextObj::impDecomposeAutoFitTextPrimitive(
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::SdrAutoFitTextPrimitive2D& rSdrAutofitTextPrimitive,
const drawinglayer::geometry::ViewInformation2D& aViewInformation) const
{
// decompose matrix to have position and size of text
basegfx::B2DVector aScale, aTranslate;
double fRotate, fShearX;
rSdrAutofitTextPrimitive.getTextRangeTransform().decompose(aScale, aTranslate, fRotate, fShearX);
// use B2DRange aAnchorTextRange for calculations
basegfx::B2DRange aAnchorTextRange(aTranslate);
aAnchorTextRange.expand(aTranslate + aScale);
// prepare outliner
const SfxItemSet& rTextItemSet = rSdrAutofitTextPrimitive.getSdrText()->GetItemSet();
SdrOutliner& rOutliner = ImpGetDrawOutliner();
SdrTextVertAdjust eVAdj = GetTextVerticalAdjust(rTextItemSet);
SdrTextHorzAdjust eHAdj = GetTextHorizontalAdjust(rTextItemSet);
const sal_uInt32 nOriginalControlWord(rOutliner.GetControlWord());
const Size aNullSize;
// set visualizing page at Outliner; needed e.g. for PageNumberField decomposition
rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));
rOutliner.SetControlWord(nOriginalControlWord|EE_CNTRL_AUTOPAGESIZE|EE_CNTRL_STRETCHING);
rOutliner.SetMinAutoPaperSize(aNullSize);
rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
// add one to rage sizes to get back to the old Rectangle and outliner measurements
const sal_uInt32 nAnchorTextWidth(FRound(aAnchorTextRange.getWidth() + 1L));
const sal_uInt32 nAnchorTextHeight(FRound(aAnchorTextRange.getHeight() + 1L));
const OutlinerParaObject* pOutlinerParaObject = rSdrAutofitTextPrimitive.getSdrText()->GetOutlinerParaObject();
OSL_ENSURE(pOutlinerParaObject, "impDecomposeBlockTextPrimitive used with no OutlinerParaObject (!)");
const bool bVerticalWritintg(pOutlinerParaObject->IsVertical());
const Size aAnchorTextSize(Size(nAnchorTextWidth, nAnchorTextHeight));
if((rSdrAutofitTextPrimitive.getWordWrap() || IsTextFrame()))
{
rOutliner.SetMaxAutoPaperSize(aAnchorTextSize);
}
if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !bVerticalWritintg)
{
rOutliner.SetMinAutoPaperSize(Size(nAnchorTextWidth, 0));
}
if(SDRTEXTVERTADJUST_BLOCK == eVAdj && bVerticalWritintg)
{
rOutliner.SetMinAutoPaperSize(Size(0, nAnchorTextHeight));
}
rOutliner.SetPaperSize(aNullSize);
rOutliner.SetUpdateMode(true);
rOutliner.SetText(*pOutlinerParaObject);
ImpAutoFitText(rOutliner,aAnchorTextSize,bVerticalWritintg);
// set visualizing page at Outliner; needed e.g. for PageNumberField decomposition
rOutliner.setVisualizedPage(GetSdrPageFromXDrawPage(aViewInformation.getVisualizedPage()));
// now get back the layouted text size from outliner
const Size aOutlinerTextSiz(rOutliner.GetPaperSize());
const basegfx::B2DVector aOutlinerScale(aOutlinerTextSiz.Width(), aOutlinerTextSiz.Height());
basegfx::B2DVector aAdjustTranslate(0.0, 0.0);
// correct horizontal translation using the now known text size
if(SDRTEXTHORZADJUST_CENTER == eHAdj || SDRTEXTHORZADJUST_RIGHT == eHAdj)
{
const double fFree(aAnchorTextRange.getWidth() - aOutlinerScale.getX());
if(SDRTEXTHORZADJUST_CENTER == eHAdj)
{
aAdjustTranslate.setX(fFree / 2.0);
}
if(SDRTEXTHORZADJUST_RIGHT == eHAdj)
{
aAdjustTranslate.setX(fFree);
}
}
// correct vertical translation using the now known text size
if(SDRTEXTVERTADJUST_CENTER == eVAdj || SDRTEXTVERTADJUST_BOTTOM == eVAdj)
{
const double fFree(aAnchorTextRange.getHeight() - aOutlinerScale.getY());
if(SDRTEXTVERTADJUST_CENTER == eVAdj)
{
aAdjustTranslate.setY(fFree / 2.0);
}
if(SDRTEXTVERTADJUST_BOTTOM == eVAdj)
{
aAdjustTranslate.setY(fFree);
}
}
// prepare matrices to apply to newly created primitives. aNewTransformA
// will get coordinates in aOutlinerScale size and positive in X, Y.
basegfx::B2DHomMatrix aNewTransformA;
basegfx::B2DHomMatrix aNewTransformB;
// translate relative to given primitive to get same rotation and shear
// as the master shape we are working on. For vertical, use the top-right
// corner
const double fStartInX(bVerticalWritintg ? aAdjustTranslate.getX() + aOutlinerScale.getX() : aAdjustTranslate.getX());
aNewTransformA.translate(fStartInX, aAdjustTranslate.getY());
// mirroring. We are now in aAnchorTextRange sizes. When mirroring in X and Y,
// move the null point which was top left to bottom right.
const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0));
const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0));
aNewTransformB.scale(bMirrorX ? -1.0 : 1.0, bMirrorY ? -1.0 : 1.0);
// in-between the translations of the single primitives will take place. Afterwards,
// the object's transformations need to be applied
aNewTransformB.shearX(fShearX);
aNewTransformB.rotate(fRotate);
aNewTransformB.translate(aTranslate.getX(), aTranslate.getY());
basegfx::B2DRange aClipRange;
// now break up text primitives.
impTextBreakupHandler aConverter(rOutliner);
aConverter.decomposeBlockTextPrimitive(aNewTransformA, aNewTransformB, aClipRange);
// cleanup outliner
rOutliner.Clear();
rOutliner.setVisualizedPage(0);
rOutliner.SetControlWord(nOriginalControlWord);
rTarget = aConverter.getPrimitive2DSequence();
}
void SdrTextObj::impDecomposeBlockTextPrimitive(
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::SdrBlockTextPrimitive2D& rSdrBlockTextPrimitive,

View file

@ -79,8 +79,7 @@ FASTBOOL SdrTextObj::AdjustTextFrameWidthAndHeight(Rectangle& rR, FASTBOOL bHgt,
{
if (bTextFrame && pModel!=NULL && !rR.IsEmpty())
{
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bFitToSize(IsFitToSize());
FASTBOOL bWdtGrow=bWdt && IsAutoGrowWidth();
FASTBOOL bHgtGrow=bHgt && IsAutoGrowHeight();
SdrTextAniKind eAniKind=GetTextAniKind();

View file

@ -73,15 +73,17 @@ sal_Bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl)
rOutl.Init( nOutlinerMode );
rOutl.SetRefDevice( pModel->GetRefDevice() );
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bFitToSize(IsFitToSize());
FASTBOOL bContourFrame=IsContourTextFrame();
ImpSetTextEditParams();
if (!bContourFrame) {
ULONG nStat=rOutl.GetControlWord();
nStat|=EE_CNTRL_AUTOPAGESIZE;
if (bFitToSize) nStat|=EE_CNTRL_STRETCHING; else nStat&=~EE_CNTRL_STRETCHING;
if (bFitToSize || IsAutoFit())
nStat|=EE_CNTRL_STRETCHING;
else
nStat&=~EE_CNTRL_STRETCHING;
rOutl.SetControlWord(nStat);
}
@ -119,7 +121,11 @@ sal_Bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl)
TakeTextRect(rOutl, aTextRect, FALSE,
&aAnchorRect/* #97097# give TRUE here, not FALSE */);
Fraction aFitXKorreg(1,1);
ImpSetCharStretching(rOutl,aTextRect,aAnchorRect,aFitXKorreg);
ImpSetCharStretching(rOutl,aTextRect.GetSize(),aAnchorRect.GetSize(),aFitXKorreg);
}
else if (IsAutoFit())
{
ImpAutoFitText(rOutl);
}
if(pOutlinerParaObject)
@ -146,8 +152,7 @@ sal_Bool SdrTextObj::BegTextEdit(SdrOutliner& rOutl)
void SdrTextObj::TakeTextEditArea(Size* pPaperMin, Size* pPaperMax, Rectangle* pViewInit, Rectangle* pViewMin) const
{
SdrFitToSizeType eFit=GetFitToSize();
FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
FASTBOOL bFitToSize(IsFitToSize());
Size aPaperMin,aPaperMax;
Rectangle aViewInit;
TakeTextAnchorRect(aViewInit);

View file

@ -84,9 +84,6 @@ void SdrTextObj::NbcSetSnapRect(const Rectangle& rRect)
if (bTextFrame && (pModel==NULL || !pModel->IsPasteResize())) { // #51139#
if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1);
if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1);
if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) {
NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0));
}
NbcAdjustTextFrameWidthAndHeight();
}
ImpCheckShear();
@ -112,9 +109,6 @@ void SdrTextObj::NbcSetLogicRect(const Rectangle& rRect)
if (bTextFrame) {
if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1);
if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1);
if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) {
NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0));
}
NbcAdjustTextFrameWidthAndHeight();
}
SetRectsDirty();
@ -228,9 +222,6 @@ void SdrTextObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fract
if (bTextFrame && (pModel==NULL || !pModel->IsPasteResize())) { // #51139#
if (nTWdt0!=nTWdt1 && IsAutoGrowWidth() ) NbcSetMinTextFrameWidth(nTWdt1);
if (nTHgt0!=nTHgt1 && IsAutoGrowHeight()) NbcSetMinTextFrameHeight(nTHgt1);
if (GetFitToSize()==SDRTEXTFIT_RESIZEATTR) {
NbcResizeTextAttributes(Fraction(nTWdt1,nTWdt0),Fraction(nTHgt1,nTHgt0));
}
NbcAdjustTextFrameWidthAndHeight();
}
ImpCheckShear();

View file

@ -502,8 +502,7 @@ SdrHitKind SdrView::PickAnything(const Point& rLogicPos, SdrViewEvent& rVEvt) co
Point aTemporaryTextRelativePosition(aLocalLogicPosition - aTextRect.TopLeft());
// FitToSize berueksichtigen
SdrFitToSizeType eFit=pTextObj->GetFitToSize();
BOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
BOOL bFitToSize(pTextObj->IsFitToSize());
if (bFitToSize) {
Fraction aX(aTextRect.GetWidth()-1,aAnchor.GetWidth()-1);
Fraction aY(aTextRect.GetHeight()-1,aAnchor.GetHeight()-1);

View file

@ -625,8 +625,8 @@ SvXMLEnumMapEntry __READONLY_DATA pXML_FitToSize_Enum[] =
{
{ XML_FALSE, drawing::TextFitToSizeType_NONE },
{ XML_TRUE, drawing::TextFitToSizeType_PROPORTIONAL },
{ XML_TRUE, drawing::TextFitToSizeType_ALLLINES },
{ XML_TRUE, drawing::TextFitToSizeType_RESIZEATTR },
{ XML_ALL, drawing::TextFitToSizeType_ALLLINES },
{ XML_SHRINK_TO_FIT,drawing::TextFitToSizeType_AUTOFIT },
{ XML_TOKEN_INVALID, 0 }
};