1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "scitems.hxx"
21 #include <editeng/eeitem.hxx>
23 #include <editeng/adjitem.hxx>
24 #include <svx/algitem.hxx>
25 #include <editeng/brshitem.hxx>
26 #include <svtools/colorcfg.hxx>
27 #include <editeng/colritem.hxx>
28 #include <editeng/editobj.hxx>
29 #include <editeng/editstat.hxx>
30 #include <editeng/fhgtitem.hxx>
31 #include <editeng/forbiddencharacterstable.hxx>
32 #include <editeng/frmdiritem.hxx>
33 #include <editeng/langitem.hxx>
34 #include <editeng/justifyitem.hxx>
35 #include <svx/rotmodit.hxx>
36 #include <editeng/scripttypeitem.hxx>
37 #include <editeng/udlnitem.hxx>
38 #include <editeng/unolingu.hxx>
39 #include <svl/zforlist.hxx>
40 #include <svl/zformat.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/metric.hxx>
43 #include <vcl/outdev.hxx>
44 #include <vcl/pdfextoutdevdata.hxx>
47 #include "document.hxx"
50 #include "patattr.hxx"
51 #include "cellform.hxx"
52 #include "editutil.hxx"
53 #include "progress.hxx"
55 #include "fillinfo.hxx"
57 #include <com/sun/star/i18n/DirectionProperty.hpp>
58 #include <comphelper/string.hxx>
60 #include <boost/ptr_container/ptr_vector.hpp>
64 using namespace com::sun::star
;
66 //! Autofilter-Breite mit column.cxx zusammenfassen
67 #define DROPDOWN_BITMAP_SIZE 18
69 #define DRAWTEXT_MAX 32767
71 const sal_uInt16 SC_SHRINKAGAIN_MAX
= 7;
73 // STATIC DATA -----------------------------------------------------------
76 // -----------------------------------------------------------------------
78 class ScDrawStringsVars
80 ScOutputData
* pOutput
; // Verbindung
82 const ScPatternAttr
* pPattern
; // Attribute
83 const SfxItemSet
* pCondSet
; // aus bedingter Formatierung
85 Font aFont
; // aus Attributen erzeugt
87 long nAscentPixel
; // always pixels
88 SvxCellOrientation eAttrOrient
;
89 SvxCellHorJustify eAttrHorJust
;
90 SvxCellVerJustify eAttrVerJust
;
91 SvxCellJustifyMethod eAttrHorJustMethod
;
92 SvxCellJustifyMethod eAttrVerJustMethod
;
93 const SvxMarginItem
* pMargin
;
97 String aString
; // Inhalte
105 ScBaseCell
* pLastCell
;
106 sal_uLong nValueFormat
;
111 sal_Bool bPixelToLogic
;
112 sal_Bool bCellContrast
;
114 Color aBackConfigColor
; // used for ScPatternAttr::GetFont calls
115 Color aTextConfigColor
;
120 ScDrawStringsVars(ScOutputData
* pData
, sal_Bool bPTL
);
121 ~ScDrawStringsVars();
123 // SetPattern = ex-SetVars
124 // SetPatternSimple: ohne Font
126 void SetPattern( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
, ScBaseCell
* pCell
, sal_uInt8 nScript
);
127 void SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
);
129 sal_Bool
SetText( ScBaseCell
* pCell
); // TRUE -> pOldPattern vergessen
131 void SetTextToWidthOrHash( ScBaseCell
* pCell
, long nWidth
);
132 void SetAutoText( const String
& rAutoText
);
134 const ScPatternAttr
* GetPattern() const { return pPattern
; }
135 SvxCellOrientation
GetOrient() const { return eAttrOrient
; }
136 SvxCellHorJustify
GetHorJust() const { return eAttrHorJust
; }
137 SvxCellVerJustify
GetVerJust() const { return eAttrVerJust
; }
138 SvxCellJustifyMethod
GetHorJustMethod() const { return eAttrHorJustMethod
; }
139 SvxCellJustifyMethod
GetVerJustMethod() const { return eAttrVerJustMethod
; }
140 const SvxMarginItem
* GetMargin() const { return pMargin
; }
142 sal_uInt16
GetLeftTotal() const { return pMargin
->GetLeftMargin() + nIndent
; }
144 const String
& GetString() const { return aString
; }
145 const Size
& GetTextSize() const { return aTextSize
; }
146 long GetOriginalWidth() const { return nOriginalWidth
; }
148 sal_uLong
GetResultValueFormat( const ScBaseCell
* pCell
) const;
150 sal_uLong
GetValueFormat() const { return nValueFormat
; }
151 sal_Bool
GetLineBreak() const { return bLineBreak
; }
152 sal_Bool
IsRepeat() const { return bRepeat
; }
153 sal_Bool
IsShrink() const { return bShrink
; }
154 void RepeatToFill( long colWidth
);
156 long GetAscent() const { return nAscentPixel
; }
157 sal_Bool
IsRotated() const { return bRotated
; }
159 void SetShrinkScale( long nScale
, sal_uInt8 nScript
);
161 sal_Bool
HasCondHeight() const { return pCondSet
&& SFX_ITEM_SET
==
162 pCondSet
->GetItemState( ATTR_FONT_HEIGHT
, sal_True
); }
164 sal_Bool
HasEditCharacters() const;
167 long GetMaxDigitWidth(); // in logic units
174 //==================================================================
176 ScDrawStringsVars::ScDrawStringsVars(ScOutputData
* pData
, sal_Bool bPTL
) :
181 eAttrOrient ( SVX_ORIENTATION_STANDARD
),
182 eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD
),
183 eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM
),
184 eAttrHorJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
185 eAttrVerJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
196 bLineBreak ( false ),
199 bPixelToLogic( bPTL
),
200 nPos( STRING_NOTFOUND
),
203 ScModule
* pScMod
= SC_MOD();
204 bCellContrast
= pOutput
->mbUseStyleColor
&&
205 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
207 const svtools::ColorConfig
& rColorConfig
= pScMod
->GetColorConfig();
208 aBackConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
);
209 aTextConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
);
212 ScDrawStringsVars::~ScDrawStringsVars()
216 void ScDrawStringsVars::SetShrinkScale( long nScale
, sal_uInt8 nScript
)
218 // text remains valid, size is updated
220 OutputDevice
* pDev
= pOutput
->mpDev
;
221 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
222 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
224 // call GetFont with a modified fraction, use only the height
226 Fraction
aFraction( nScale
, 100 );
227 if ( !bPixelToLogic
)
228 aFraction
*= pOutput
->aZoomY
;
230 pPattern
->GetFont( aTmpFont
, SC_AUTOCOL_RAW
, pFmtDevice
, &aFraction
, pCondSet
, nScript
);
231 long nNewHeight
= aTmpFont
.GetHeight();
232 if ( nNewHeight
> 0 )
233 aFont
.SetHeight( nNewHeight
);
235 // set font and dependent variables as in SetPattern
237 pDev
->SetFont( aFont
);
238 if ( pFmtDevice
!= pDev
)
239 pFmtDevice
->SetFont( aFont
);
241 aMetric
= pFmtDevice
->GetFontMetric();
242 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
244 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
245 MapMode aOld
= pDefaultDev
->GetMapMode();
246 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
247 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
248 pDefaultDev
->SetMapMode( aOld
);
251 nAscentPixel
= aMetric
.GetAscent();
253 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
255 SetAutoText( aString
); // same text again, to get text size
260 template<typename _ItemType
, typename _EnumType
>
261 _EnumType
lcl_GetValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
263 const _ItemType
& rItem
= static_cast<const _ItemType
&>(rPattern
.GetItem(nWhich
, pCondSet
));
264 return static_cast<_EnumType
>(rItem
.GetValue());
267 bool lcl_GetBoolValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
269 return lcl_GetValue
<SfxBoolItem
, bool>(rPattern
, nWhich
, pCondSet
);
274 void ScDrawStringsVars::SetPattern( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
,
275 ScBaseCell
* pCell
, sal_uInt8 nScript
)
285 // pPattern auswerten
287 OutputDevice
* pDev
= pOutput
->mpDev
;
288 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
289 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
293 ScAutoFontColorMode eColorMode
;
294 if ( pOutput
->mbUseStyleColor
)
296 if ( pOutput
->mbForceAutoColor
)
297 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREALL
: SC_AUTOCOL_IGNOREFONT
;
299 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREBACK
: SC_AUTOCOL_DISPLAY
;
302 eColorMode
= SC_AUTOCOL_PRINT
;
305 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, NULL
, pCondSet
, nScript
,
306 &aBackConfigColor
, &aTextConfigColor
);
308 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, &pOutput
->aZoomY
, pCondSet
, nScript
,
309 &aBackConfigColor
, &aTextConfigColor
);
310 aFont
.SetAlign(ALIGN_BASELINE
);
314 eAttrOrient
= pPattern
->GetCellOrientation( pCondSet
);
318 eAttrHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
320 eAttrVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)pPattern
->GetItem( ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
321 if ( eAttrVerJust
== SVX_VER_JUSTIFY_STANDARD
)
322 eAttrVerJust
= SVX_VER_JUSTIFY_BOTTOM
;
324 // justification method
326 eAttrHorJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
);
327 eAttrVerJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
);
331 bLineBreak
= ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
, pCondSet
)).GetValue();
333 // handle "repeat" alignment
335 bRepeat
= ( eAttrHorJust
== SVX_HOR_JUSTIFY_REPEAT
);
338 // "repeat" disables rotation (before constructing the font)
339 eAttrOrient
= SVX_ORIENTATION_STANDARD
;
341 // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
343 eAttrHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
349 case SVX_ORIENTATION_STANDARD
:
351 bRotated
= (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
, pCondSet
)).GetValue() != 0) &&
354 case SVX_ORIENTATION_STACKED
:
358 case SVX_ORIENTATION_TOPBOTTOM
:
362 case SVX_ORIENTATION_BOTTOMTOP
:
367 OSL_FAIL("Falscher SvxCellOrientation Wert");
372 aFont
.SetOrientation( nRot
);
376 if (pOutput
->mbSyntaxMode
)
377 pOutput
->SetSyntaxColor( &aFont
, pCell
);
379 pDev
->SetFont( aFont
);
380 if ( pFmtDevice
!= pDev
)
381 pFmtDevice
->SetFont( aFont
);
383 aMetric
= pFmtDevice
->GetFontMetric();
386 // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
387 // -> Metric vom Bildschirm nehmen (wie EditEngine!)
390 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
392 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
393 MapMode aOld
= pDefaultDev
->GetMapMode();
394 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
395 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
396 pDefaultDev
->SetMapMode( aOld
);
399 nAscentPixel
= aMetric
.GetAscent();
401 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
403 Color
aULineColor( ((const SvxUnderlineItem
&)pPattern
->GetItem( ATTR_FONT_UNDERLINE
, pCondSet
)).GetColor() );
404 pDev
->SetTextLineColor( aULineColor
);
406 Color
aOLineColor( ((const SvxOverlineItem
&)pPattern
->GetItem( ATTR_FONT_OVERLINE
, pCondSet
)).GetColor() );
407 pDev
->SetOverlineColor( aOLineColor
);
411 nValueFormat
= pPattern
->GetNumberFormat( pOutput
->mpDoc
->GetFormatTable(), pCondSet
);
415 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
416 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
)
417 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
423 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
425 // zumindest die Text-Groesse muss neu geholt werden
426 //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
431 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
)
437 // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
440 pCondSet
= pSet
; //! noetig ???
444 sal_uLong nOld
= nValueFormat
;
445 const SfxPoolItem
* pFormItem
;
446 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_VALUE_FORMAT
,sal_True
,&pFormItem
) != SFX_ITEM_SET
)
447 pFormItem
= &pPattern
->GetItem(ATTR_VALUE_FORMAT
);
448 const SfxPoolItem
* pLangItem
;
449 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_LANGUAGE_FORMAT
,sal_True
,&pLangItem
) != SFX_ITEM_SET
)
450 pLangItem
= &pPattern
->GetItem(ATTR_LANGUAGE_FORMAT
);
451 nValueFormat
= pOutput
->mpDoc
->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
452 ((SfxUInt32Item
*)pFormItem
)->GetValue(),
453 ((SvxLanguageItem
*)pLangItem
)->GetLanguage() );
455 if (nValueFormat
!= nOld
)
456 pLastCell
= NULL
; // immer neu formatieren
460 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
462 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
)
463 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
469 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
472 inline sal_Bool
SameValue( ScBaseCell
* pCell
, ScBaseCell
* pOldCell
) // pCell ist != 0
474 return pOldCell
&& pOldCell
->GetCellType() == CELLTYPE_VALUE
&&
475 pCell
->GetCellType() == CELLTYPE_VALUE
&&
476 ((ScValueCell
*)pCell
)->GetValue() == ((ScValueCell
*)pOldCell
)->GetValue();
479 sal_Bool
ScDrawStringsVars::SetText( ScBaseCell
* pCell
)
481 sal_Bool bChanged
= false;
485 if ( !SameValue( pCell
, pLastCell
) )
487 pLastCell
= pCell
; // Zelle merken
490 sal_uLong nFormat
= GetValueFormat();
491 rtl::OUString aOUString
= aString
;
492 ScCellFormat::GetString( pCell
,
493 nFormat
, aOUString
, &pColor
,
494 *pOutput
->mpDoc
->GetFormatTable(),
495 pOutput
->mbShowNullValues
,
496 pOutput
->mbShowFormulas
,
501 nPos
= aString
.Search( 0x1B );
502 if ( nPos
!= STRING_NOTFOUND
)
504 nChar
= aString
.GetChar( nPos
+ 1 );
505 // delete placeholder and char to repeat
506 aString
.Erase( nPos
, 2 );
511 nPos
= STRING_NOTFOUND
;
514 if (aString
.Len() > DRAWTEXT_MAX
)
515 aString
.Erase(DRAWTEXT_MAX
);
517 if ( pColor
&& !pOutput
->mbSyntaxMode
&& !( pOutput
->mbUseStyleColor
&& pOutput
->mbForceAutoColor
) )
519 OutputDevice
* pDev
= pOutput
->mpDev
;
520 aFont
.SetColor(*pColor
);
521 pDev
->SetFont( aFont
); // nur fuer Ausgabe
523 pLastCell
= NULL
; // naechstes Mal wieder hierherkommen
528 // sonst String/Groesse behalten
534 aTextSize
= Size(0,0);
541 void ScDrawStringsVars::SetHashText()
543 SetAutoText(rtl::OUString("###"));
546 void ScDrawStringsVars::RepeatToFill( long colWidth
)
548 if ( nPos
== STRING_NOTFOUND
|| nPos
> aString
.Len() )
551 long charWidth
= pOutput
->pFmtDevice
->GetTextWidth(rtl::OUString(nChar
));
552 if ( charWidth
< 1) return;
554 colWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(colWidth
,0)).Width();
555 // Are there restrictions on the cell type we should filter out here ?
556 long aSpaceToFill
= ( colWidth
- aTextSize
.Width() );
558 if ( aSpaceToFill
<= charWidth
)
561 long nCharsToInsert
= aSpaceToFill
/ charWidth
;
562 OUStringBuffer aFill
;
563 comphelper::string::padToLength(aFill
, nCharsToInsert
, nChar
);
564 aString
.Insert( aFill
.makeStringAndClear(), nPos
);
568 void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell
* pCell
, long nWidth
)
570 // #i113045# do the single-character width calculations in logic units
572 nWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(nWidth
,0)).Width();
577 CellType eType
= pCell
->GetCellType();
578 if (eType
!= CELLTYPE_VALUE
&& eType
!= CELLTYPE_FORMULA
)
579 // must be a value or formula cell.
582 if (eType
== CELLTYPE_FORMULA
)
584 ScFormulaCell
* pFCell
= static_cast<ScFormulaCell
*>(pCell
);
585 if (pFCell
->GetErrCode() != 0 || pOutput
->mbShowFormulas
)
587 SetHashText(); // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
590 // If it's formula, the result must be a value.
591 if (!pFCell
->IsValue())
594 if (pFCell
->GetFormatType() != NUMBERFORMAT_NUMBER
)
596 // Make sure the format type implicitly set by the interpreter is
597 // of pure numeric type. We don't want to adjust date and time
604 sal_uLong nFormat
= GetResultValueFormat(pCell
);
605 if ((nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) != 0)
607 // Not 'General' number format. Set hash text and bail out.
612 double fVal
= (eType
== CELLTYPE_VALUE
) ?
613 static_cast<ScValueCell
*>(pCell
)->GetValue() : static_cast<ScFormulaCell
*>(pCell
)->GetValue();
615 const SvNumberformat
* pNumFormat
= pOutput
->mpDoc
->GetFormatTable()->GetEntry(nFormat
);
619 long nMaxDigit
= GetMaxDigitWidth();
620 sal_uInt16 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
622 OUString
sTempOut(aString
);
623 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
626 // Failed to get output string. Bail out.
631 sal_uInt8 nSignCount
= 0, nDecimalCount
= 0, nExpCount
= 0;
632 xub_StrLen nLen
= aString
.Len();
633 sal_Unicode cDecSep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
.getStr()[0];
634 for (xub_StrLen i
= 0; i
< nLen
; ++i
)
636 sal_Unicode c
= aString
.GetChar(i
);
637 if (c
== sal_Unicode('-'))
639 else if (c
== cDecSep
)
641 else if (c
== sal_Unicode('E'))
645 // #i112250# A small value might be formatted as "0" when only counting the digits,
646 // but fit into the column when considering the smaller width of the decimal separator.
647 if (aString
.EqualsAscii("0") && fVal
!= 0.0)
651 nWidth
+= (nMaxDigit
- GetDotWidth()) * nDecimalCount
;
653 nWidth
+= (nMaxDigit
- GetSignWidth()) * nSignCount
;
655 nWidth
+= (nMaxDigit
- GetExpWidth()) * nExpCount
;
657 if (nDecimalCount
|| nSignCount
|| nExpCount
)
660 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
661 OUString
sTempOut(aString
);
662 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
665 // Failed to get output string. Bail out.
671 long nActualTextWidth
= pOutput
->pFmtDevice
->GetTextWidth(aString
);
672 if (nActualTextWidth
> nWidth
)
674 // Even after the decimal adjustment the text doesn't fit. Give up.
680 pLastCell
= NULL
; // #i113022# equal cell and format in another column may give different string
683 void ScDrawStringsVars::SetAutoText( const String
& rAutoText
)
687 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
688 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
689 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
690 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
692 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
694 double fMul
= pOutput
->GetStretch();
695 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
698 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
699 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
701 long nTemp
= aTextSize
.Height();
702 aTextSize
.Height() = aTextSize
.Width();
703 aTextSize
.Width() = nTemp
;
706 nOriginalWidth
= aTextSize
.Width();
708 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
710 pLastCell
= NULL
; // derselbe Text kann in der naechsten Zelle wieder passen
713 long ScDrawStringsVars::GetMaxDigitWidth()
715 if (nMaxDigitWidth
> 0)
716 return nMaxDigitWidth
;
718 sal_Char cZero
= '0';
719 for (sal_Char i
= 0; i
< 10; ++i
)
721 sal_Char cDigit
= cZero
+ i
;
722 long n
= pOutput
->pFmtDevice
->GetTextWidth(rtl::OUString(cDigit
));
723 nMaxDigitWidth
= ::std::max(nMaxDigitWidth
, n
);
725 return nMaxDigitWidth
;
728 long ScDrawStringsVars::GetSignWidth()
733 nSignWidth
= pOutput
->pFmtDevice
->GetTextWidth(rtl::OUString('-'));
737 long ScDrawStringsVars::GetDotWidth()
742 const ::rtl::OUString
& sep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
;
743 nDotWidth
= pOutput
->pFmtDevice
->GetTextWidth(sep
);
747 long ScDrawStringsVars::GetExpWidth()
752 nExpWidth
= pOutput
->pFmtDevice
->GetTextWidth(rtl::OUString('E'));
756 void ScDrawStringsVars::TextChanged()
758 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
759 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
760 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
761 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
763 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
765 double fMul
= pOutput
->GetStretch();
766 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
769 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
770 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
772 long nTemp
= aTextSize
.Height();
773 aTextSize
.Height() = aTextSize
.Width();
774 aTextSize
.Width() = nTemp
;
777 nOriginalWidth
= aTextSize
.Width();
779 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
782 sal_Bool
ScDrawStringsVars::HasEditCharacters() const
784 static const sal_Unicode pChars
[] =
786 CHAR_NBSP
, CHAR_SHY
, CHAR_ZWSP
, CHAR_LRM
, CHAR_RLM
, CHAR_NBHY
, CHAR_ZWNBSP
, 0
788 return aString
.SearchChar( pChars
) != STRING_NOTFOUND
;
791 sal_uLong
ScDrawStringsVars::GetResultValueFormat( const ScBaseCell
* pCell
) const
793 // Get the effective number format, including formula result types.
794 // This assumes that a formula cell has already been calculated.
796 if ( (nValueFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) == 0 && pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
797 return static_cast<const ScFormulaCell
*>(pCell
)->GetStandardFormat(*pOutput
->mpDoc
->GetFormatTable(), nValueFormat
);
802 //==================================================================
804 double ScOutputData::GetStretch()
806 if ( mpRefDevice
->IsMapMode() )
808 // If a non-trivial MapMode is set, its scale is now already
809 // taken into account in the OutputDevice's font handling
810 // (OutputDevice::ImplNewFont, see #95414#).
811 // The old handling below is only needed for pixel output.
815 // calculation in double is faster than Fraction multiplication
816 // and doesn't overflow
818 if ( mpRefDevice
== pFmtDevice
)
820 MapMode aOld
= mpRefDevice
->GetMapMode();
821 return ((double)aOld
.GetScaleY()) / ((double)aOld
.GetScaleX()) * ((double)aZoomY
) / ((double)aZoomX
);
825 // when formatting for printer, device map mode has already been taken care of
826 return ((double)aZoomY
) / ((double)aZoomX
);
830 //==================================================================
836 static void lcl_DoHyperlinkResult( OutputDevice
* pDev
, const Rectangle
& rRect
, ScBaseCell
* pCell
)
838 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
840 rtl::OUString aCellText
;
842 if ( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
844 ScFormulaCell
* pFCell
= static_cast<ScFormulaCell
*>(pCell
);
845 if ( pFCell
->IsHyperLinkCell() )
846 pFCell
->GetURLResult( aURL
, aCellText
);
849 if ( !aURL
.isEmpty() && pPDFData
)
851 vcl::PDFExtOutDevBookmarkEntry aBookmark
;
852 aBookmark
.nLinkId
= pPDFData
->CreateLink( rRect
);
853 aBookmark
.aBookmark
= aURL
;
854 std::vector
< vcl::PDFExtOutDevBookmarkEntry
>& rBookmarks
= pPDFData
->GetBookmarks();
855 rBookmarks
.push_back( aBookmark
);
859 void ScOutputData::SetSyntaxColor( Font
* pFont
, ScBaseCell
* pCell
)
863 switch (pCell
->GetCellType())
866 pFont
->SetColor( *pValueColor
);
868 case CELLTYPE_STRING
:
869 pFont
->SetColor( *pTextColor
);
871 case CELLTYPE_FORMULA
:
872 pFont
->SetColor( *pFormulaColor
);
876 // added to avoid warnings
882 static void lcl_SetEditColor( EditEngine
& rEngine
, const Color
& rColor
)
884 ESelection
aSel( 0, 0, rEngine
.GetParagraphCount(), 0 );
885 SfxItemSet
aSet( rEngine
.GetEmptyItemSet() );
886 aSet
.Put( SvxColorItem( rColor
, EE_CHAR_COLOR
) );
887 rEngine
.QuickSetAttribs( aSet
, aSel
);
888 // function is called with update mode set to FALSE
891 void ScOutputData::SetEditSyntaxColor( EditEngine
& rEngine
, ScBaseCell
* pCell
)
896 switch (pCell
->GetCellType())
899 aColor
= *pValueColor
;
901 case CELLTYPE_STRING
:
902 aColor
= *pTextColor
;
904 case CELLTYPE_FORMULA
:
905 aColor
= *pFormulaColor
;
909 // added to avoid warnings
912 lcl_SetEditColor( rEngine
, aColor
);
916 sal_Bool
ScOutputData::GetMergeOrigin( SCCOL nX
, SCROW nY
, SCSIZE nArrY
,
917 SCCOL
& rOverX
, SCROW
& rOverY
,
918 sal_Bool bVisRowChanged
)
920 sal_Bool bDoMerge
= false;
921 sal_Bool bIsLeft
= ( nX
== nVisX1
);
922 sal_Bool bIsTop
= ( nY
== nVisY1
) || bVisRowChanged
;
924 CellInfo
* pInfo
= &pRowInfo
[nArrY
].pCellInfo
[nX
+1];
925 if ( pInfo
->bHOverlapped
&& pInfo
->bVOverlapped
)
926 bDoMerge
= bIsLeft
&& bIsTop
;
927 else if ( pInfo
->bHOverlapped
)
929 else if ( pInfo
->bVOverlapped
)
934 sal_Bool bHOver
= pInfo
->bHOverlapped
;
935 sal_Bool bVOver
= pInfo
->bVOverlapped
;
938 while (bHOver
) // nY konstant
941 bHidden
= mpDoc
->ColHidden(rOverX
, nTab
);
942 if ( !bDoMerge
&& !bHidden
)
945 if (rOverX
>= nX1
&& !bHidden
)
947 bHOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bHOverlapped
;
948 bVOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bVOverlapped
;
952 sal_uInt16 nOverlap
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
953 rOverX
, rOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue();
954 bHOver
= ((nOverlap
& SC_MF_HOR
) != 0);
955 bVOver
= ((nOverlap
& SC_MF_VER
) != 0);
962 bHidden
= mpDoc
->RowHidden(rOverY
, nTab
);
963 if ( !bDoMerge
&& !bHidden
)
967 --nArrY
; // lokale Kopie !
969 if (rOverX
>= nX1
&& rOverY
>= nY1
&&
970 !mpDoc
->ColHidden(rOverX
, nTab
) &&
971 !mpDoc
->RowHidden(rOverY
, nTab
) &&
972 pRowInfo
[nArrY
].nRowNo
== rOverY
)
974 bHOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bHOverlapped
;
975 bVOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bVOverlapped
;
979 sal_uInt16 nOverlap
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
980 rOverX
, rOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue();
981 bHOver
= ((nOverlap
& SC_MF_HOR
) != 0);
982 bVOver
= ((nOverlap
& SC_MF_VER
) != 0);
989 inline sal_Bool
StringDiffer( const ScPatternAttr
*& rpOldPattern
, const ScPatternAttr
*& rpNewPattern
)
991 OSL_ENSURE( rpNewPattern
, "pNewPattern" );
993 if ( rpNewPattern
== rpOldPattern
)
995 else if ( !rpOldPattern
)
997 else if ( &rpNewPattern
->GetItem( ATTR_FONT
) != &rpOldPattern
->GetItem( ATTR_FONT
) )
999 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT
) )
1001 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT
) )
1003 else if ( &rpNewPattern
->GetItem( ATTR_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_HEIGHT
) )
1005 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) )
1007 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) )
1009 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_WEIGHT
) )
1011 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) )
1013 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) )
1015 else if ( &rpNewPattern
->GetItem( ATTR_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_FONT_POSTURE
) )
1017 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) )
1019 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) )
1021 else if ( &rpNewPattern
->GetItem( ATTR_FONT_UNDERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_UNDERLINE
) )
1023 else if ( &rpNewPattern
->GetItem( ATTR_FONT_OVERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_OVERLINE
) )
1025 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WORDLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_WORDLINE
) )
1027 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) != &rpOldPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) )
1029 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CONTOUR
) != &rpOldPattern
->GetItem( ATTR_FONT_CONTOUR
) )
1031 else if ( &rpNewPattern
->GetItem( ATTR_FONT_SHADOWED
) != &rpOldPattern
->GetItem( ATTR_FONT_SHADOWED
) )
1033 else if ( &rpNewPattern
->GetItem( ATTR_FONT_COLOR
) != &rpOldPattern
->GetItem( ATTR_FONT_COLOR
) )
1035 else if ( &rpNewPattern
->GetItem( ATTR_HOR_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_HOR_JUSTIFY
) )
1037 else if ( &rpNewPattern
->GetItem( ATTR_HOR_JUSTIFY_METHOD
) != &rpOldPattern
->GetItem( ATTR_HOR_JUSTIFY_METHOD
) )
1039 else if ( &rpNewPattern
->GetItem( ATTR_VER_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_VER_JUSTIFY
) )
1041 else if ( &rpNewPattern
->GetItem( ATTR_VER_JUSTIFY_METHOD
) != &rpOldPattern
->GetItem( ATTR_VER_JUSTIFY_METHOD
) )
1043 else if ( &rpNewPattern
->GetItem( ATTR_STACKED
) != &rpOldPattern
->GetItem( ATTR_STACKED
) )
1045 else if ( &rpNewPattern
->GetItem( ATTR_LINEBREAK
) != &rpOldPattern
->GetItem( ATTR_LINEBREAK
) )
1047 else if ( &rpNewPattern
->GetItem( ATTR_MARGIN
) != &rpOldPattern
->GetItem( ATTR_MARGIN
) )
1049 else if ( &rpNewPattern
->GetItem( ATTR_ROTATE_VALUE
) != &rpOldPattern
->GetItem( ATTR_ROTATE_VALUE
) )
1051 else if ( &rpNewPattern
->GetItem( ATTR_FORBIDDEN_RULES
) != &rpOldPattern
->GetItem( ATTR_FORBIDDEN_RULES
) )
1053 else if ( &rpNewPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) != &rpOldPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) )
1055 else if ( &rpNewPattern
->GetItem( ATTR_FONT_RELIEF
) != &rpOldPattern
->GetItem( ATTR_FONT_RELIEF
) )
1057 else if ( &rpNewPattern
->GetItem( ATTR_BACKGROUND
) != &rpOldPattern
->GetItem( ATTR_BACKGROUND
) )
1058 return sal_True
; // needed with automatic text color
1061 rpOldPattern
= rpNewPattern
;
1066 static inline void lcl_CreateInterpretProgress( sal_Bool
& bProgress
, ScDocument
* pDoc
,
1067 ScFormulaCell
* pFCell
)
1069 if ( !bProgress
&& pFCell
->GetDirty() )
1071 ScProgress::CreateInterpretProgress( pDoc
, sal_True
);
1072 bProgress
= sal_True
;
1076 inline sal_uInt8
GetScriptType( ScDocument
* pDoc
, ScBaseCell
* pCell
,
1077 const ScPatternAttr
* pPattern
,
1078 const SfxItemSet
* pCondSet
)
1080 return pDoc
->GetCellScriptType( pCell
, pPattern
->GetNumberFormat( pDoc
->GetFormatTable(), pCondSet
) );
1083 inline sal_Bool
IsAmbiguousScript( sal_uInt8 nScript
)
1085 return ( nScript
!= SCRIPTTYPE_LATIN
&&
1086 nScript
!= SCRIPTTYPE_ASIAN
&&
1087 nScript
!= SCRIPTTYPE_COMPLEX
);
1090 sal_Bool
ScOutputData::IsEmptyCellText( RowInfo
* pThisRowInfo
, SCCOL nX
, SCROW nY
)
1092 // pThisRowInfo may be NULL
1095 if ( pThisRowInfo
&& nX
<= nX2
)
1096 bEmpty
= pThisRowInfo
->pCellInfo
[nX
+1].bEmptyCellText
;
1098 bEmpty
= ( mpDoc
->GetCell( ScAddress( nX
, nY
, nTab
) ) == NULL
);
1100 if ( !bEmpty
&& ( nX
< nX1
|| nX
> nX2
|| !pThisRowInfo
) )
1102 // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
1103 // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
1105 sal_Bool bIsPrint
= ( eType
== OUTTYPE_PRINTER
);
1107 if ( bIsPrint
|| bTabProtected
)
1109 const ScProtectionAttr
* pAttr
= (const ScProtectionAttr
*)
1110 mpDoc
->GetEffItem( nX
, nY
, nTab
, ATTR_PROTECTION
);
1111 if ( bIsPrint
&& pAttr
->GetHidePrint() )
1113 else if ( bTabProtected
)
1115 if ( pAttr
->GetHideCell() )
1117 else if ( mbShowFormulas
&& pAttr
->GetHideFormula() )
1119 ScBaseCell
* pCell
= mpDoc
->GetCell( ScAddress( nX
, nY
, nTab
) );
1120 if ( pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
)
1129 void ScOutputData::GetVisibleCell( SCCOL nCol
, SCROW nRow
, SCTAB nTabP
, ScBaseCell
*& rpCell
)
1131 mpDoc
->GetCell( nCol
, nRow
, nTabP
, rpCell
);
1132 if ( rpCell
&& IsEmptyCellText( NULL
, nCol
, nRow
) )
1136 sal_Bool
ScOutputData::IsAvailable( SCCOL nX
, SCROW nY
)
1138 // apply the same logic here as in DrawStrings/DrawEdit:
1139 // Stop at non-empty or merged or overlapped cell,
1140 // where a note is empty as well as a cell that's hidden by protection settings
1142 const ScBaseCell
* pCell
= mpDoc
->GetCell( ScAddress( nX
, nY
, nTab
) );
1143 if ( pCell
&& pCell
->GetCellType() != CELLTYPE_NOTE
&& !IsEmptyCellText( NULL
, nX
, nY
) )
1148 const ScPatternAttr
* pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1149 if ( ((const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
)).IsMerged() ||
1150 ((const ScMergeFlagAttr
&)pPattern
->GetItem(ATTR_MERGE_FLAG
)).IsOverlapped() )
1158 // nX, nArrY: loop variables from DrawStrings / DrawEdit
1159 // nPosX, nPosY: corresponding positions for nX, nArrY
1160 // nCellX, nCellY: position of the cell that contains the text
1161 // nNeeded: Text width, including margin
1162 // rPattern: cell format at nCellX, nCellY
1163 // nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings
1164 // bCellIsValue: if set, don't extend into empty cells
1165 // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
1166 // bOverwrite: if set, also extend into non-empty cells (for rotated text)
1167 // rParam output: various area parameters.
1169 void ScOutputData::GetOutputArea( SCCOL nX
, SCSIZE nArrY
, long nPosX
, long nPosY
,
1170 SCCOL nCellX
, SCROW nCellY
, long nNeeded
,
1171 const ScPatternAttr
& rPattern
,
1172 sal_uInt16 nHorJustify
, bool bCellIsValue
,
1173 bool bBreak
, bool bOverwrite
,
1174 OutputAreaParam
& rParam
)
1176 // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
1177 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1179 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1181 long nCellPosX
= nPosX
; // find nCellX position, starting at nX/nPosX
1182 SCCOL nCompCol
= nX
;
1183 while ( nCellX
> nCompCol
)
1185 //! extra member function for width?
1186 long nColWidth
= ( nCompCol
<= nX2
) ?
1187 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1188 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1189 nCellPosX
+= nColWidth
* nLayoutSign
;
1192 while ( nCellX
< nCompCol
)
1195 long nColWidth
= ( nCompCol
<= nX2
) ?
1196 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1197 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1198 nCellPosX
-= nColWidth
* nLayoutSign
;
1201 long nCellPosY
= nPosY
; // find nCellY position, starting at nArrY/nPosY
1202 SCSIZE nCompArr
= nArrY
;
1203 SCROW nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1204 while ( nCellY
> nCompRow
)
1206 if ( nCompArr
+ 1 < nArrCount
)
1208 nCellPosY
+= pRowInfo
[nCompArr
].nHeight
;
1210 nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1214 sal_uInt16 nDocHeight
= mpDoc
->GetRowHeight( nCompRow
, nTab
);
1216 nCellPosY
+= (long) ( nDocHeight
* mnPPTY
);
1220 nCellPosY
-= (long) mpDoc
->GetScaledRowHeight( nCellY
, nCompRow
-1, nTab
, mnPPTY
);
1222 const ScMergeAttr
* pMerge
= (const ScMergeAttr
*)&rPattern
.GetItem( ATTR_MERGE
);
1223 sal_Bool bMerged
= pMerge
->IsMerged();
1224 long nMergeCols
= pMerge
->GetColMerge();
1225 if ( nMergeCols
== 0 )
1227 long nMergeRows
= pMerge
->GetRowMerge();
1228 if ( nMergeRows
== 0 )
1232 long nMergeSizeX
= 0;
1233 for ( i
=0; i
<nMergeCols
; i
++ )
1235 long nColWidth
= ( nCellX
+i
<= nX2
) ?
1236 pRowInfo
[0].pCellInfo
[nCellX
+i
+1].nWidth
:
1237 (long) ( mpDoc
->GetColWidth( sal::static_int_cast
<SCCOL
>(nCellX
+i
), nTab
) * mnPPTX
);
1238 nMergeSizeX
+= nColWidth
;
1240 long nMergeSizeY
= 0;
1242 if ( rThisRowInfo
.nRowNo
== nCellY
)
1244 // take first row's height from row info
1245 nMergeSizeY
+= rThisRowInfo
.nHeight
;
1246 nDirect
= 1; // skip in loop
1248 // following rows always from document
1249 nMergeSizeY
+= (long) mpDoc
->GetScaledRowHeight( nCellY
+nDirect
, nCellY
+nMergeRows
-1, nTab
, mnPPTY
);
1251 --nMergeSizeX
; // leave out the grid horizontally, also for alignment (align between grid lines)
1253 rParam
.mnColWidth
= nMergeSizeX
; // store the actual column width.
1256 // construct the rectangles using logical left/right values (justify is called at the end)
1259 // rAlignRect is the single cell or merged area, used for alignment.
1261 rParam
.maAlignRect
.Left() = nCellPosX
;
1262 rParam
.maAlignRect
.Right() = nCellPosX
+ ( nMergeSizeX
- 1 ) * nLayoutSign
;
1263 rParam
.maAlignRect
.Top() = nCellPosY
;
1264 rParam
.maAlignRect
.Bottom() = nCellPosY
+ nMergeSizeY
- 1;
1266 // rClipRect is all cells that are used for output.
1267 // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1269 rParam
.maClipRect
= rParam
.maAlignRect
;
1270 if ( nNeeded
> nMergeSizeX
)
1272 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)nHorJustify
;
1274 long nMissing
= nNeeded
- nMergeSizeX
;
1275 long nLeftMissing
= 0;
1276 long nRightMissing
= 0;
1279 case SVX_HOR_JUSTIFY_LEFT
:
1280 nRightMissing
= nMissing
;
1282 case SVX_HOR_JUSTIFY_RIGHT
:
1283 nLeftMissing
= nMissing
;
1285 case SVX_HOR_JUSTIFY_CENTER
:
1286 nLeftMissing
= nMissing
/ 2;
1287 nRightMissing
= nMissing
- nLeftMissing
;
1291 // added to avoid warnings
1295 // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1297 ::std::swap( nLeftMissing
, nRightMissing
);
1299 SCCOL nRightX
= nCellX
;
1300 SCCOL nLeftX
= nCellX
;
1301 if ( !bMerged
&& !bCellIsValue
&& !bBreak
)
1303 // look for empty cells into which the text can be extended
1305 while ( nRightMissing
> 0 && nRightX
< MAXCOL
&& ( bOverwrite
|| IsAvailable( nRightX
+1, nCellY
) ) )
1308 long nAdd
= (long) ( mpDoc
->GetColWidth( nRightX
, nTab
) * mnPPTX
);
1309 nRightMissing
-= nAdd
;
1310 rParam
.maClipRect
.Right() += nAdd
* nLayoutSign
;
1312 if ( rThisRowInfo
.nRowNo
== nCellY
&& nRightX
>= nX1
&& nRightX
<= nX2
)
1313 rThisRowInfo
.pCellInfo
[nRightX
].bHideGrid
= sal_True
;
1316 while ( nLeftMissing
> 0 && nLeftX
> 0 && ( bOverwrite
|| IsAvailable( nLeftX
-1, nCellY
) ) )
1318 if ( rThisRowInfo
.nRowNo
== nCellY
&& nLeftX
>= nX1
&& nLeftX
<= nX2
)
1319 rThisRowInfo
.pCellInfo
[nLeftX
].bHideGrid
= sal_True
;
1322 long nAdd
= (long) ( mpDoc
->GetColWidth( nLeftX
, nTab
) * mnPPTX
);
1323 nLeftMissing
-= nAdd
;
1324 rParam
.maClipRect
.Left() -= nAdd
* nLayoutSign
;
1328 // Set flag and reserve space for clipping mark triangle,
1329 // even if rThisRowInfo isn't for nCellY (merged cells).
1330 if ( nRightMissing
> 0 && bMarkClipped
&& nRightX
>= nX1
&& nRightX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1332 rThisRowInfo
.pCellInfo
[nRightX
+1].nClipMark
|= SC_CLIPMARK_RIGHT
;
1333 bAnyClipped
= sal_True
;
1334 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1335 rParam
.maClipRect
.Right() -= nMarkPixel
* nLayoutSign
;
1337 if ( nLeftMissing
> 0 && bMarkClipped
&& nLeftX
>= nX1
&& nLeftX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1339 rThisRowInfo
.pCellInfo
[nLeftX
+1].nClipMark
|= SC_CLIPMARK_LEFT
;
1340 bAnyClipped
= sal_True
;
1341 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1342 rParam
.maClipRect
.Left() += nMarkPixel
* nLayoutSign
;
1345 rParam
.mbLeftClip
= ( nLeftMissing
> 0 );
1346 rParam
.mbRightClip
= ( nRightMissing
> 0 );
1350 rParam
.mbLeftClip
= rParam
.mbRightClip
= false;
1352 // leave space for AutoFilter on screen
1353 // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1355 if ( eType
==OUTTYPE_WINDOW
&&
1356 ( static_cast<const ScMergeFlagAttr
&>(rPattern
.GetItem(ATTR_MERGE_FLAG
)).GetValue() & SC_MF_AUTO
) &&
1357 ( !bBreak
|| mpRefDevice
== pFmtDevice
) )
1359 // filter drop-down width is now independent from row height
1360 const long nFilter
= DROPDOWN_BITMAP_SIZE
;
1361 sal_Bool bFit
= ( nNeeded
+ nFilter
<= nMergeSizeX
);
1362 if ( bFit
|| bCellIsValue
)
1364 // content fits even in the remaining area without the filter button
1365 // -> align within that remaining area
1367 rParam
.maAlignRect
.Right() -= nFilter
* nLayoutSign
;
1368 rParam
.maClipRect
.Right() -= nFilter
* nLayoutSign
;
1370 // if a number doesn't fit, don't hide part of the number behind the button
1371 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1374 rParam
.mbLeftClip
= rParam
.mbRightClip
= sal_True
;
1379 // justify both rectangles for alignment calculation, use with DrawText etc.
1381 rParam
.maAlignRect
.Justify();
1382 rParam
.maClipRect
.Justify();
1387 bool beginsWithRTLCharacter(const rtl::OUString
& rStr
)
1392 switch (ScGlobal::pCharClass
->getCharacterDirection(rStr
, 0))
1394 case i18n::DirectionProperty_RIGHT_TO_LEFT
:
1395 case i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC
:
1396 case i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING
:
1397 case i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
:
1408 void ScOutputData::DrawStrings( sal_Bool bPixelToLogic
)
1410 OSL_ENSURE( mpDev
== mpRefDevice
||
1411 mpDev
->GetMapMode().GetMapUnit() == mpRefDevice
->GetMapMode().GetMapUnit(),
1412 "DrawStrings: unterschiedliche MapUnits ?!?!" );
1414 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, mpDev
->GetExtOutDevData() );
1416 sal_Bool bWasIdleDisabled
= mpDoc
->IsIdleDisabled();
1417 mpDoc
->DisableIdle( true );
1419 ScDrawStringsVars
aVars( this, bPixelToLogic
);
1421 sal_Bool bProgress
= false;
1423 long nInitPosX
= nScrX
;
1425 nInitPosX
+= nMirrorW
- 1; // pixels
1426 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1428 SCCOL nLastContentCol
= MAXCOL
;
1430 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
1431 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
1432 SCCOL nLoopStartX
= nX1
;
1434 --nLoopStartX
; // start before nX1 for rest of long text to the left
1436 // variables for GetOutputArea
1437 OutputAreaParam aAreaParam
;
1438 sal_Bool bCellIsValue
= false;
1439 long nNeededWidth
= 0;
1440 SvxCellHorJustify eOutHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
1441 const ScPatternAttr
* pPattern
= NULL
;
1442 const SfxItemSet
* pCondSet
= NULL
;
1443 const ScPatternAttr
* pOldPattern
= NULL
;
1444 const SfxItemSet
* pOldCondSet
= NULL
;
1445 sal_uInt8 nOldScript
= 0;
1447 // alternative pattern instances in case we need to modify the pattern
1448 // before processing the cell value.
1449 ::boost::ptr_vector
<ScPatternAttr
> aAltPatterns
;
1452 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1454 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1455 if ( pThisRowInfo
->bChanged
)
1457 SCROW nY
= pThisRowInfo
->nRowNo
;
1458 long nPosX
= nInitPosX
;
1459 if ( nLoopStartX
< nX1
)
1460 nPosX
-= pRowInfo
[0].pCellInfo
[nLoopStartX
+1].nWidth
* nLayoutSign
;
1461 for (SCCOL nX
=nLoopStartX
; nX
<=nX2
; nX
++)
1463 sal_Bool bMergeEmpty
= false;
1464 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
1465 sal_Bool bEmpty
= nX
< nX1
|| pInfo
->bEmptyCellText
;
1467 SCCOL nCellX
= nX
; // position where the cell really starts
1469 sal_Bool bDoCell
= false;
1470 sal_Bool bNeedEdit
= false;
1473 // Part of a merged cell?
1476 sal_Bool bOverlapped
= ( pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
);
1481 SCCOL nOverX
; // start of the merged cells
1483 sal_Bool bVisChanged
= !pRowInfo
[nArrY
-1].bChanged
;
1484 if (GetMergeOrigin( nX
,nY
, nArrY
, nOverX
,nOverY
, bVisChanged
))
1491 bMergeEmpty
= sal_True
;
1495 // Rest of a long text further to the left?
1498 if ( bEmpty
&& !bMergeEmpty
&& nX
< nX1
&& !bOverlapped
)
1501 while (nTempX
> 0 && IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1504 if ( nTempX
< nX1
&&
1505 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1506 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX1
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1514 // Rest of a long text further to the right?
1517 if ( bEmpty
&& !bMergeEmpty
&& nX
== nX2
&& !bOverlapped
)
1519 // don't have to look further than nLastContentCol
1522 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1526 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1527 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1535 // normal visible cell
1542 // don't output the cell that's being edited
1545 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
1548 // skip text in cell if data bar is set and only value selected
1551 if(pInfo
->pDataBar
&& !pInfo
->pDataBar
->mbShowValue
)
1556 // output the cell text
1559 ScBaseCell
* pCell
= NULL
;
1562 if ( nCellY
== nY
&& nCellX
== nX
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1563 pCell
= pThisRowInfo
->pCellInfo
[nCellX
+1].pCell
;
1565 GetVisibleCell( nCellX
, nCellY
, nTab
, pCell
); // get from document
1568 else if ( pCell
->GetCellType() == CELLTYPE_EDIT
)
1569 bNeedEdit
= sal_True
;
1571 if (bDoCell
&& !bNeedEdit
)
1573 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1575 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
1576 pPattern
= rCellInfo
.pPatternAttr
;
1577 pCondSet
= rCellInfo
.pConditionSet
;
1581 // #i68085# pattern from cell info for hidden columns is null,
1582 // test for null is quicker than using column flags
1583 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1584 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1587 else // get from document
1589 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1590 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1593 if (pCell
->HasValueData() &&
1594 static_cast<const SfxBoolItem
&>(
1595 pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue())
1597 // Disable line break when the cell content is numeric.
1598 aAltPatterns
.push_back(new ScPatternAttr(*pPattern
));
1599 ScPatternAttr
* pAltPattern
= &aAltPatterns
.back();
1600 SfxBoolItem
aLineBreak(ATTR_LINEBREAK
, false);
1601 pAltPattern
->GetItemSet().Put(aLineBreak
);
1602 pPattern
= pAltPattern
;
1605 sal_uInt8 nScript
= GetScriptType( mpDoc
, pCell
, pPattern
, pCondSet
);
1606 if (nScript
== 0) nScript
= ScGlobal::GetDefaultScriptType();
1607 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
||
1608 nScript
!= nOldScript
|| mbSyntaxMode
)
1610 if ( StringDiffer(pOldPattern
,pPattern
) ||
1611 pCondSet
!= pOldCondSet
|| nScript
!= nOldScript
|| mbSyntaxMode
)
1612 aVars
.SetPattern( pPattern
, pCondSet
, pCell
, nScript
);
1614 aVars
.SetPatternSimple( pPattern
, pCondSet
);
1615 pOldPattern
= pPattern
;
1616 pOldCondSet
= pCondSet
;
1617 nOldScript
= nScript
;
1620 // use edit engine for rotated, stacked or mixed-script text
1621 if ( aVars
.GetOrient() == SVX_ORIENTATION_STACKED
||
1622 aVars
.IsRotated() || IsAmbiguousScript(nScript
) )
1623 bNeedEdit
= sal_True
;
1625 if (bDoCell
&& !bNeedEdit
)
1627 sal_Bool bFormulaCell
= (pCell
->GetCellType() == CELLTYPE_FORMULA
);
1629 lcl_CreateInterpretProgress( bProgress
, mpDoc
, (ScFormulaCell
*)pCell
);
1630 if ( aVars
.SetText(pCell
) )
1632 bNeedEdit
= aVars
.HasEditCharacters() ||
1633 (bFormulaCell
&& ((ScFormulaCell
*)pCell
)->IsMultilineResult());
1635 long nTotalMargin
= 0;
1636 if (bDoCell
&& !bNeedEdit
)
1638 CellType eCellType
= pCell
->GetCellType();
1639 bCellIsValue
= ( eCellType
== CELLTYPE_VALUE
);
1640 if ( eCellType
== CELLTYPE_FORMULA
)
1642 ScFormulaCell
* pFCell
= (ScFormulaCell
*)pCell
;
1643 bCellIsValue
= pFCell
->IsRunning() || pFCell
->IsValue();
1646 if (aVars
.GetHorJust() == SVX_HOR_JUSTIFY_STANDARD
)
1648 // fdo#32530: Default alignment depends on value vs
1649 // string, and the direction of the 1st letter.
1650 if (beginsWithRTLCharacter(aVars
.GetString()))
1651 eOutHorJust
= bCellIsValue
? SVX_HOR_JUSTIFY_LEFT
: SVX_HOR_JUSTIFY_RIGHT
;
1653 eOutHorJust
= bCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
1656 eOutHorJust
= aVars
.GetHorJust();
1658 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
1659 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
1661 sal_Bool bBreak
= ( aVars
.GetLineBreak() || aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
);
1662 // #i111387# #o11817313# disable automatic line breaks only for "General" number format
1663 if ( bBreak
&& bCellIsValue
&& ( aVars
.GetResultValueFormat(pCell
) % SV_COUNTRY_LANGUAGE_OFFSET
) == 0 )
1666 sal_Bool bRepeat
= aVars
.IsRepeat() && !bBreak
;
1667 sal_Bool bShrink
= aVars
.IsShrink() && !bBreak
&& !bRepeat
;
1670 static_cast<long>(aVars
.GetLeftTotal() * mnPPTX
) +
1671 static_cast<long>(aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1673 nNeededWidth
= aVars
.GetTextSize().Width() + nTotalMargin
;
1675 // GetOutputArea gives justfied rectangles
1676 GetOutputArea( nX
, nArrY
, nPosX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
1677 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
1678 bCellIsValue
|| bRepeat
|| bShrink
, bBreak
, false,
1681 aVars
.RepeatToFill( aAreaParam
.mnColWidth
- nTotalMargin
);
1684 if ( aVars
.GetOrient() != SVX_ORIENTATION_STANDARD
)
1686 // Only horizontal scaling is handled here.
1687 // DrawEdit is used to vertically scale 90 deg rotated text.
1688 bNeedEdit
= sal_True
;
1690 else if ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) // horizontal
1692 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1693 long nScaleSize
= aVars
.GetTextSize().Width(); // without margin
1695 if ( nScaleSize
> 0 ) // 0 if the text is empty (formulas, number formats)
1697 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
1699 aVars
.SetShrinkScale( nScale
, nOldScript
);
1700 long nNewSize
= aVars
.GetTextSize().Width();
1702 sal_uInt16 nShrinkAgain
= 0;
1703 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
1705 // If the text is still too large, reduce the scale again by 10%, until it fits,
1706 // at most 7 times (it's less than 50% of the calculated scale then).
1708 nScale
= ( nScale
* 9 ) / 10;
1709 aVars
.SetShrinkScale( nScale
, nOldScript
);
1710 nNewSize
= aVars
.GetTextSize().Width();
1713 // If even at half the size the font still isn't rendered smaller,
1714 // fall back to normal clipping (showing ### for numbers).
1715 if ( nNewSize
<= nAvailable
)
1716 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1723 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
)
1725 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1726 long nRepeatSize
= aVars
.GetTextSize().Width(); // without margin
1727 // When formatting for the printer, the text sizes don't always add up.
1728 // Round down (too few repetitions) rather than exceeding the cell size then:
1729 if ( pFmtDevice
!= mpRefDevice
)
1731 if ( nRepeatSize
> 0 )
1733 long nRepeatCount
= nAvailable
/ nRepeatSize
;
1734 if ( nRepeatCount
> 1 )
1736 String aCellStr
= aVars
.GetString();
1737 String aRepeated
= aCellStr
;
1738 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
1739 aRepeated
.Append( aCellStr
);
1740 aVars
.SetAutoText( aRepeated
);
1745 // use edit engine if automatic line breaks are needed
1748 if ( aVars
.GetOrient() == SVX_ORIENTATION_STANDARD
)
1749 bNeedEdit
= ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
);
1752 long nHeight
= aVars
.GetTextSize().Height() +
1753 (long)(aVars
.GetMargin()->GetTopMargin()*mnPPTY
) +
1754 (long)(aVars
.GetMargin()->GetBottomMargin()*mnPPTY
);
1755 bNeedEdit
= ( nHeight
> aAreaParam
.maClipRect
.GetHeight() );
1761 aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
&&
1762 aVars
.GetHorJustMethod() == SVX_JUSTIFY_METHOD_DISTRIBUTE
;
1767 // mark the cell in CellInfo to be drawn in DrawEdit:
1768 // Cells to the left are marked directly, cells to the
1769 // right are handled by the flag for nX2
1770 SCCOL nMarkX
= ( nCellX
<= nX2
) ? nCellX
: nX2
;
1771 RowInfo
* pMarkRowInfo
= ( nCellY
== nY
) ? pThisRowInfo
: &pRowInfo
[0];
1772 pMarkRowInfo
->pCellInfo
[nMarkX
+1].bEditEngine
= sal_True
;
1773 bDoCell
= false; // don't draw here
1777 if ( bCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
1780 aVars
.SetHashText();
1782 // Adjust the decimals to fit the available column width.
1783 aVars
.SetTextToWidthOrHash(pCell
, aAreaParam
.mnColWidth
- nTotalMargin
);
1785 nNeededWidth
= aVars
.GetTextSize().Width() +
1786 (long) ( aVars
.GetLeftTotal() * mnPPTX
) +
1787 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1788 if ( nNeededWidth
<= aAreaParam
.maClipRect
.GetWidth() )
1789 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1791 // If the "###" replacement doesn't fit into the cells, no clip marks
1792 // are shown, as the "###" already denotes too little space.
1793 // The rectangles from the first GetOutputArea call remain valid.
1796 long nJustPosX
= aAreaParam
.maAlignRect
.Left(); // "justified" - effect of alignment will be added
1797 long nJustPosY
= aAreaParam
.maAlignRect
.Top();
1798 long nAvailWidth
= aAreaParam
.maAlignRect
.GetWidth();
1799 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight();
1801 sal_Bool bOutside
= ( aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
1802 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
1804 aAreaParam
.maClipRect
.Left() = nScrX
;
1805 aAreaParam
.mbLeftClip
= sal_True
;
1807 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
1809 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
1810 aAreaParam
.mbRightClip
= sal_True
;
1813 sal_Bool bHClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
1814 sal_Bool bVClip
= false;
1816 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
1818 aAreaParam
.maClipRect
.Top() = nScrY
;
1821 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
1823 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
1828 // horizontalen Platz testen
1831 sal_Bool bRightAdjusted
= false; // to correct text width calculation later
1832 sal_Bool bNeedEditEngine
= false;
1833 if ( !bNeedEditEngine
&& !bOutside
)
1835 switch (eOutHorJust
)
1837 case SVX_HOR_JUSTIFY_LEFT
:
1838 nJustPosX
+= (long) ( aVars
.GetLeftTotal() * mnPPTX
);
1840 case SVX_HOR_JUSTIFY_RIGHT
:
1841 nJustPosX
+= nAvailWidth
- aVars
.GetTextSize().Width() -
1842 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1843 bRightAdjusted
= sal_True
;
1845 case SVX_HOR_JUSTIFY_CENTER
:
1846 nJustPosX
+= ( nAvailWidth
- aVars
.GetTextSize().Width() +
1847 (long) ( aVars
.GetLeftTotal() * mnPPTX
) -
1848 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
) ) / 2;
1852 // added to avoid warnings
1856 long nTestClipHeight
= aVars
.GetTextSize().Height();
1857 switch (aVars
.GetVerJust())
1859 case SVX_VER_JUSTIFY_TOP
:
1860 case SVX_VER_JUSTIFY_BLOCK
:
1862 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1864 nTestClipHeight
+= nTop
;
1867 case SVX_VER_JUSTIFY_BOTTOM
:
1869 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1870 nJustPosY
+= nOutHeight
- aVars
.GetTextSize().Height() - nBot
;
1871 nTestClipHeight
+= nBot
;
1874 case SVX_VER_JUSTIFY_CENTER
:
1876 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1877 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1878 nJustPosY
+= ( nOutHeight
+ nTop
-
1879 aVars
.GetTextSize().Height() - nBot
) / 2;
1880 nTestClipHeight
+= Abs( nTop
- nBot
);
1885 // added to avoid warnings
1889 if ( nTestClipHeight
> nOutHeight
)
1891 // kein vertikales Clipping beim Drucken von Zellen mit
1892 // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1893 if ( eType
!= OUTTYPE_PRINTER
||
1894 ( mpDoc
->GetRowFlags( nCellY
, nTab
) & CR_MANUALSIZE
) ||
1895 ( aVars
.HasCondHeight() ) )
1899 if ( bHClip
|| bVClip
)
1901 // nur die betroffene Dimension clippen,
1902 // damit bei nicht-proportionalem Resize nicht alle
1903 // rechtsbuendigen Zahlen abgeschnitten werden:
1907 aAreaParam
.maClipRect
.Left() = nScrX
;
1908 aAreaParam
.maClipRect
.Right() = nScrX
+nScrW
;
1912 aAreaParam
.maClipRect
.Top() = nScrY
;
1913 aAreaParam
.maClipRect
.Bottom() = nScrY
+nScrH
;
1916 // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1917 // so it can be modified here
1919 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
1924 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
1927 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
1930 Point
aURLStart( nJustPosX
, nJustPosY
); // copy before modifying for orientation
1932 switch (aVars
.GetOrient())
1934 case SVX_ORIENTATION_STANDARD
:
1935 nJustPosY
+= aVars
.GetAscent();
1937 case SVX_ORIENTATION_TOPBOTTOM
:
1938 nJustPosX
+= aVars
.GetTextSize().Width() - aVars
.GetAscent();
1940 case SVX_ORIENTATION_BOTTOMTOP
:
1941 nJustPosY
+= aVars
.GetTextSize().Height();
1942 nJustPosX
+= aVars
.GetAscent();
1946 // added to avoid warnings
1950 // When clipping, the visible part is now completely defined by the alignment,
1951 // there's no more special handling to show the right part of RTL text.
1953 Point
aDrawTextPos( nJustPosX
, nJustPosY
);
1954 if ( bPixelToLogic
)
1956 // undo text width adjustment in pixels
1958 aDrawTextPos
.X() += aVars
.GetTextSize().Width();
1960 aDrawTextPos
= mpRefDevice
->PixelToLogic( aDrawTextPos
);
1962 // redo text width adjustment in logic units
1964 aDrawTextPos
.X() -= aVars
.GetOriginalWidth();
1967 // in Metafiles immer DrawTextArray, damit die Positionen mit
1968 // aufgezeichnet werden (fuer nicht-proportionales Resize):
1970 String aString
= aVars
.GetString();
1971 if (bMetaFile
|| pFmtDevice
!= mpDev
|| aZoomX
!= aZoomY
)
1973 sal_Int32
* pDX
= new sal_Int32
[aString
.Len()];
1974 pFmtDevice
->GetTextArray( aString
, pDX
);
1976 if ( !mpRefDevice
->GetConnectMetaFile() ||
1977 mpRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
1979 double fMul
= GetStretch();
1980 xub_StrLen nLen
= aString
.Len();
1981 for (xub_StrLen i
=0; i
<nLen
; i
++)
1982 pDX
[i
] = (long)(pDX
[i
] / fMul
+ 0.5);
1985 mpDev
->DrawTextArray( aDrawTextPos
, aString
, pDX
);
1989 mpDev
->DrawText( aDrawTextPos
, aString
);
1991 if ( bHClip
|| bVClip
)
1996 mpDev
->SetClipRegion();
1999 // PDF: whole-cell hyperlink from formula?
2000 sal_Bool bHasURL
= pPDFData
&& pCell
&& pCell
->GetCellType() == CELLTYPE_FORMULA
&&
2001 static_cast<ScFormulaCell
*>(pCell
)->IsHyperLinkCell();
2004 Rectangle
aURLRect( aURLStart
, aVars
.GetTextSize() );
2005 lcl_DoHyperlinkResult( mpDev
, aURLRect
, pCell
);
2009 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2012 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2015 ScProgress::DeleteInterpretProgress();
2016 mpDoc
->DisableIdle( bWasIdleDisabled
);
2019 // -------------------------------------------------------------------------------
2021 ScFieldEditEngine
* ScOutputData::CreateOutputEditEngine()
2023 ScFieldEditEngine
* pEngine
= new ScFieldEditEngine(mpDoc
, mpDoc
->GetEnginePool());
2024 pEngine
->SetUpdateMode( false );
2025 // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
2026 pEngine
->SetRefDevice( pFmtDevice
);
2027 sal_uLong nCtrl
= pEngine
->GetControlWord();
2028 if ( bShowSpellErrors
)
2029 nCtrl
|= EE_CNTRL_ONLINESPELLING
;
2030 if ( eType
== OUTTYPE_PRINTER
)
2031 nCtrl
&= ~EE_CNTRL_MARKFIELDS
;
2032 if ( eType
== OUTTYPE_WINDOW
&& mpRefDevice
== pFmtDevice
)
2033 nCtrl
&= ~EE_CNTRL_FORMAT100
; // use the actual MapMode
2034 pEngine
->SetControlWord( nCtrl
);
2035 mpDoc
->ApplyAsianEditSettings( *pEngine
);
2036 pEngine
->EnableAutoColor( mbUseStyleColor
);
2037 pEngine
->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection
)mpDoc
->GetEditTextDirection( nTab
) );
2041 static void lcl_ClearEdit( EditEngine
& rEngine
) // Text und Attribute
2043 rEngine
.SetUpdateMode( false );
2045 rEngine
.SetText(EMPTY_STRING
);
2046 // keine Para-Attribute uebrigbehalten...
2047 const SfxItemSet
& rPara
= rEngine
.GetParaAttribs(0);
2049 rEngine
.SetParaAttribs( 0,
2050 SfxItemSet( *rPara
.GetPool(), rPara
.GetRanges() ) );
2053 static sal_Bool
lcl_SafeIsValue( ScBaseCell
* pCell
)
2058 sal_Bool bRet
= false;
2059 switch ( pCell
->GetCellType() )
2061 case CELLTYPE_VALUE
:
2064 case CELLTYPE_FORMULA
:
2066 ScFormulaCell
* pFCell
= (ScFormulaCell
*)pCell
;
2067 if ( pFCell
->IsRunning() || pFCell
->IsValue() )
2073 // added to avoid warnings
2079 static void lcl_ScaleFonts( EditEngine
& rEngine
, long nPercent
)
2081 sal_Bool bUpdateMode
= rEngine
.GetUpdateMode();
2083 rEngine
.SetUpdateMode( false );
2085 sal_uInt16 nParCount
= rEngine
.GetParagraphCount();
2086 for (sal_uInt16 nPar
=0; nPar
<nParCount
; nPar
++)
2088 std::vector
<sal_uInt16
> aPortions
;
2089 rEngine
.GetPortions( nPar
, aPortions
);
2091 sal_uInt16 nStart
= 0;
2092 for ( std::vector
<sal_uInt16
>::const_iterator
it(aPortions
.begin()); it
!= aPortions
.end(); ++it
)
2094 sal_uInt16 nEnd
= *it
;
2095 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
2096 SfxItemSet aAttribs
= rEngine
.GetAttribs( aSel
);
2098 long nWestern
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT
)).GetHeight();
2099 long nCJK
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CJK
)).GetHeight();
2100 long nCTL
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CTL
)).GetHeight();
2102 nWestern
= ( nWestern
* nPercent
) / 100;
2103 nCJK
= ( nCJK
* nPercent
) / 100;
2104 nCTL
= ( nCTL
* nPercent
) / 100;
2106 aAttribs
.Put( SvxFontHeightItem( nWestern
, 100, EE_CHAR_FONTHEIGHT
) );
2107 aAttribs
.Put( SvxFontHeightItem( nCJK
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
2108 aAttribs
.Put( SvxFontHeightItem( nCTL
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
2110 rEngine
.QuickSetAttribs( aAttribs
, aSel
); //! remove paragraph attributes from aAttribs?
2117 rEngine
.SetUpdateMode( sal_True
);
2120 static long lcl_GetEditSize( EditEngine
& rEngine
, sal_Bool bWidth
, sal_Bool bSwap
, long nAttrRotate
)
2127 long nRealWidth
= (long) rEngine
.CalcTextWidth();
2128 long nRealHeight
= rEngine
.GetTextHeight();
2130 // assuming standard mode, otherwise width isn't used
2132 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100th degrees
2133 double nAbsCos
= fabs( cos( nRealOrient
) );
2134 double nAbsSin
= fabs( sin( nRealOrient
) );
2136 return (long) ( nRealWidth
* nAbsCos
+ nRealHeight
* nAbsSin
);
2138 return (long) ( nRealHeight
* nAbsCos
+ nRealWidth
* nAbsSin
);
2141 return (long) rEngine
.CalcTextWidth();
2143 return rEngine
.GetTextHeight();
2147 void ScOutputData::ShrinkEditEngine( EditEngine
& rEngine
, const Rectangle
& rAlignRect
,
2148 long nLeftM
, long nTopM
, long nRightM
, long nBottomM
,
2149 sal_Bool bWidth
, sal_uInt16 nOrient
, long nAttrRotate
, sal_Bool bPixelToLogic
,
2150 long& rEngineWidth
, long& rEngineHeight
, long& rNeededPixel
, bool& rLeftClip
, bool& rRightClip
)
2156 long nScaleSize
= bPixelToLogic
?
2157 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2159 // Don't scale if it fits already.
2160 // Allowing to extend into the margin, to avoid scaling at optimal height.
2161 if ( nScaleSize
<= rAlignRect
.GetHeight() )
2164 sal_Bool bSwap
= ( nOrient
== SVX_ORIENTATION_TOPBOTTOM
|| nOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2165 long nAvailable
= rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2166 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2168 lcl_ScaleFonts( rEngine
, nScale
);
2169 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2170 long nNewSize
= bPixelToLogic
?
2171 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2173 sal_uInt16 nShrinkAgain
= 0;
2174 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2176 // further reduce, like in DrawStrings
2177 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2178 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2179 nNewSize
= bPixelToLogic
?
2180 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2184 // sizes for further processing (alignment etc):
2185 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, bSwap
, nAttrRotate
);
2186 long nPixelWidth
= bPixelToLogic
?
2187 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2188 rNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
2190 else if ( rLeftClip
|| rRightClip
)
2194 long nAvailable
= rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2195 long nScaleSize
= rNeededPixel
- nLeftM
- nRightM
; // without margin
2197 if ( nScaleSize
<= nAvailable
)
2200 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2202 lcl_ScaleFonts( rEngine
, nScale
);
2203 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, false, nAttrRotate
);
2204 long nNewSize
= bPixelToLogic
?
2205 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2207 sal_uInt16 nShrinkAgain
= 0;
2208 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2210 // further reduce, like in DrawStrings
2211 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2212 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, false, nAttrRotate
);
2213 nNewSize
= bPixelToLogic
?
2214 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2217 if ( nNewSize
<= nAvailable
)
2218 rLeftClip
= rRightClip
= false;
2220 // sizes for further processing (alignment etc):
2221 rNeededPixel
= nNewSize
+ nLeftM
+ nRightM
;
2222 rEngineHeight
= lcl_GetEditSize( rEngine
, false, false, nAttrRotate
);
2226 ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr
* pPattern
, const SfxItemSet
* pCondSet
, bool bCellIsValue
) :
2227 meHorJust( lcl_GetValue
<SvxHorJustifyItem
, SvxCellHorJustify
>(*pPattern
, ATTR_HOR_JUSTIFY
, pCondSet
) ),
2228 meVerJust( lcl_GetValue
<SvxVerJustifyItem
, SvxCellVerJustify
>(*pPattern
, ATTR_VER_JUSTIFY
, pCondSet
) ),
2229 meHorJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
) ),
2230 meVerJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
) ),
2231 meOrient( pPattern
->GetCellOrientation(pCondSet
) ),
2233 mnX(0), mnY(0), mnCellX(0), mnCellY(0),
2234 mnPosX(0), mnPosY(0), mnInitPosX(0),
2235 mbBreak( (meHorJust
== SVX_HOR_JUSTIFY_BLOCK
) || lcl_GetBoolValue(*pPattern
, ATTR_LINEBREAK
, pCondSet
) ),
2236 mbCellIsValue(bCellIsValue
),
2237 mbAsianVertical(false),
2238 mbPixelToLogic(false),
2239 mbHyphenatorSet(false),
2243 mpPattern(pPattern
),
2244 mpCondSet(pCondSet
),
2250 bool ScOutputData::DrawEditParam::readCellContent(
2251 ScDocument
* pDoc
, bool bShowNullValues
, bool bShowFormulas
, bool bSyntaxMode
, bool bUseStyleColor
, bool bForceAutoColor
, bool& rWrapFields
)
2255 OSL_FAIL("pCell == NULL");
2259 if (mpCell
->GetCellType() == CELLTYPE_EDIT
)
2261 const EditTextObject
* pData
;
2262 ((ScEditCell
*)mpCell
)->GetData(pData
);
2266 mpEngine
->SetText(*pData
);
2268 if ( mbBreak
&& !mbAsianVertical
&& pData
->HasField() )
2270 // Fields aren't wrapped, so clipping is enabled to prevent
2271 // a field from being drawn beyond the cell size
2278 OSL_FAIL("pData == 0");
2284 sal_uLong nFormat
= mpPattern
->GetNumberFormat(
2285 pDoc
->GetFormatTable(), mpCondSet
);
2286 rtl::OUString aString
;
2288 ScCellFormat::GetString( mpCell
,
2289 nFormat
,aString
, &pColor
,
2290 *pDoc
->GetFormatTable(),
2295 mpEngine
->SetText(aString
);
2296 if ( pColor
&& !bSyntaxMode
&& !( bUseStyleColor
&& bForceAutoColor
) )
2297 lcl_SetEditColor( *mpEngine
, *pColor
);
2302 void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor
)
2304 // syntax highlighting mode is ignored here
2305 // StringDiffer doesn't look at hyphenate, language items
2307 if (mpPattern
== mpOldPattern
&& mpCondSet
== mpOldCondSet
)
2310 sal_Int32 nConfBackColor
= SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
2311 bool bCellContrast
= bUseStyleColor
&&
2312 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2314 SfxItemSet
* pSet
= new SfxItemSet( mpEngine
->GetEmptyItemSet() );
2315 mpPattern
->FillEditItemSet( pSet
, mpCondSet
);
2317 mpEngine
->SetDefaults( pSet
);
2318 mpOldPattern
= mpPattern
;
2319 mpOldCondSet
= mpCondSet
;
2321 sal_uLong nControl
= mpEngine
->GetControlWord();
2322 if (meOrient
== SVX_ORIENTATION_STACKED
)
2323 nControl
|= EE_CNTRL_ONECHARPERLINE
;
2325 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
2326 mpEngine
->SetControlWord( nControl
);
2328 if ( !mbHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
2330 // set hyphenator the first time it is needed
2331 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
2332 mpEngine
->SetHyphenator( xXHyphenator
);
2333 mbHyphenatorSet
= true;
2336 Color aBackCol
= ((const SvxBrushItem
&)mpPattern
->GetItem( ATTR_BACKGROUND
, mpCondSet
)).GetColor();
2337 if ( bUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
2338 aBackCol
.SetColor( nConfBackColor
);
2339 mpEngine
->SetBackgroundColor( aBackCol
);
2342 void ScOutputData::DrawEditParam::calcMargins(long& rTopM
, long& rLeftM
, long& rBottomM
, long& rRightM
, double nPPTX
, double nPPTY
) const
2344 const SvxMarginItem
& rMargin
=
2345 static_cast<const SvxMarginItem
&>(mpPattern
->GetItem(ATTR_MARGIN
, mpCondSet
));
2347 sal_uInt16 nIndent
= 0;
2348 if (meHorJust
== SVX_HOR_JUSTIFY_LEFT
)
2349 nIndent
= lcl_GetValue
<SfxUInt16Item
, sal_uInt16
>(*mpPattern
, ATTR_INDENT
, mpCondSet
);
2351 rLeftM
= static_cast<long>(((rMargin
.GetLeftMargin() + nIndent
) * nPPTX
));
2352 rTopM
= static_cast<long>((rMargin
.GetTopMargin() * nPPTY
));
2353 rRightM
= static_cast<long>((rMargin
.GetRightMargin() * nPPTX
));
2354 rBottomM
= static_cast<long>((rMargin
.GetBottomMargin() * nPPTY
));
2357 void ScOutputData::DrawEditParam::calcPaperSize(
2358 Size
& rPaperSize
, const Rectangle
& rAlignRect
, double nPPTX
, double nPPTY
) const
2360 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2361 calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, nPPTX
, nPPTY
);
2363 if (isVerticallyOriented())
2365 rPaperSize
.Width() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2366 rPaperSize
.Height() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2370 rPaperSize
.Width() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2371 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2374 if (mbAsianVertical
)
2376 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2377 // Subtract some extra value from the height or else the text would go
2378 // outside the cell area. The value of 5 is arbitrary, and is based
2379 // entirely on heuristics.
2380 rPaperSize
.Height() -= 5;
2384 void ScOutputData::DrawEditParam::getEngineSize(ScFieldEditEngine
* pEngine
, long& rWidth
, long& rHeight
) const
2386 long nEngineWidth
= 0;
2387 if (!mbBreak
|| meOrient
== SVX_ORIENTATION_STACKED
|| mbAsianVertical
)
2388 nEngineWidth
= static_cast<long>(pEngine
->CalcTextWidth());
2390 long nEngineHeight
= pEngine
->GetTextHeight();
2392 if (isVerticallyOriented())
2394 long nTemp
= nEngineWidth
;
2395 nEngineWidth
= nEngineHeight
;
2396 nEngineHeight
= nTemp
;
2399 if (meOrient
== SVX_ORIENTATION_STACKED
)
2400 nEngineWidth
= nEngineWidth
* 11 / 10;
2402 rWidth
= nEngineWidth
;
2403 rHeight
= nEngineHeight
;
2406 bool ScOutputData::DrawEditParam::hasLineBreak() const
2408 return (mbBreak
|| (meOrient
== SVX_ORIENTATION_STACKED
) || mbAsianVertical
);
2411 bool ScOutputData::DrawEditParam::isHyperlinkCell() const
2416 if (mpCell
->GetCellType() != CELLTYPE_FORMULA
)
2419 return static_cast<ScFormulaCell
*>(mpCell
)->IsHyperLinkCell();
2422 bool ScOutputData::DrawEditParam::isVerticallyOriented() const
2424 return (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| meOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2427 void ScOutputData::DrawEditParam::calcStartPosForVertical(
2428 Point
& rLogicStart
, long nCellWidth
, long nEngineWidth
, long nTopM
, OutputDevice
* pRefDevice
)
2430 OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
2433 rLogicStart
= pRefDevice
->PixelToLogic(rLogicStart
);
2437 // vertical adjustment is within the EditEngine
2439 rLogicStart
.Y() += pRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
2441 rLogicStart
.Y() += nTopM
;
2445 case SVX_HOR_JUSTIFY_CENTER
:
2446 rLogicStart
.X() += (nCellWidth
- nEngineWidth
) / 2;
2448 case SVX_HOR_JUSTIFY_RIGHT
:
2449 rLogicStart
.X() += nCellWidth
- nEngineWidth
;
2457 void ScOutputData::DrawEditParam::setAlignmentToEngine()
2459 if (isVerticallyOriented() || mbAsianVertical
)
2461 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2464 case SVX_VER_JUSTIFY_TOP
:
2465 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2466 SVX_ADJUST_LEFT
: SVX_ADJUST_RIGHT
;
2468 case SVX_VER_JUSTIFY_CENTER
:
2469 eSvxAdjust
= SVX_ADJUST_CENTER
;
2471 case SVX_VER_JUSTIFY_BOTTOM
:
2472 case SVX_VER_JUSTIFY_STANDARD
:
2473 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2474 SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
2476 case SVX_VER_JUSTIFY_BLOCK
:
2477 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2481 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2482 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2484 if (meHorJust
== SVX_HOR_JUSTIFY_BLOCK
)
2485 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2489 // horizontal alignment now may depend on cell content
2490 // (for values with number formats with mixed script types)
2491 // -> always set adjustment
2493 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2494 if (meOrient
== SVX_ORIENTATION_STACKED
)
2495 eSvxAdjust
= SVX_ADJUST_CENTER
;
2498 if (meOrient
== SVX_ORIENTATION_STANDARD
)
2501 case SVX_HOR_JUSTIFY_STANDARD
:
2502 eSvxAdjust
= mbCellIsValue
? SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
2504 case SVX_HOR_JUSTIFY_LEFT
:
2505 case SVX_HOR_JUSTIFY_REPEAT
: // nicht implementiert
2506 eSvxAdjust
= SVX_ADJUST_LEFT
;
2508 case SVX_HOR_JUSTIFY_RIGHT
:
2509 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2511 case SVX_HOR_JUSTIFY_CENTER
:
2512 eSvxAdjust
= SVX_ADJUST_CENTER
;
2514 case SVX_HOR_JUSTIFY_BLOCK
:
2515 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2521 case SVX_VER_JUSTIFY_TOP
:
2522 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2524 case SVX_VER_JUSTIFY_CENTER
:
2525 eSvxAdjust
= SVX_ADJUST_CENTER
;
2527 case SVX_VER_JUSTIFY_BOTTOM
:
2528 case SVX_VER_JUSTIFY_STANDARD
:
2529 eSvxAdjust
= SVX_ADJUST_LEFT
;
2531 case SVX_VER_JUSTIFY_BLOCK
:
2532 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2537 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2539 if (mbAsianVertical
)
2541 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2542 if (meHorJust
== SVX_HOR_JUSTIFY_BLOCK
)
2543 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2547 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod
, EE_PARA_JUST_METHOD
) );
2548 if (meVerJust
== SVX_VER_JUSTIFY_BLOCK
)
2549 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2553 mpEngine
->SetVertical(mbAsianVertical
);
2554 if (mpCell
&& mpCell
->GetCellType() == CELLTYPE_EDIT
)
2556 // We need to synchronize the vertical mode in the EditTextObject
2557 // instance too. No idea why we keep this state in two separate
2559 ScEditCell
* pEditCell
= static_cast<ScEditCell
*>(mpCell
);
2560 const EditTextObject
* pData
= pEditCell
->GetData();
2562 const_cast<EditTextObject
*>(pData
)->SetVertical(mbAsianVertical
);
2566 bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine
* pEngine
)
2568 if (meHorJust
== SVX_HOR_JUSTIFY_RIGHT
|| meHorJust
== SVX_HOR_JUSTIFY_CENTER
||
2569 (meHorJust
== SVX_HOR_JUSTIFY_STANDARD
&& mbCellIsValue
))
2571 SvxAdjust eEditAdjust
= (meHorJust
== SVX_HOR_JUSTIFY_CENTER
) ?
2572 SVX_ADJUST_CENTER
: SVX_ADJUST_RIGHT
;
2574 pEngine
->SetUpdateMode(false);
2575 pEngine
->SetDefaultItem( SvxAdjustItem(eEditAdjust
, EE_PARA_JUST
) );
2576 pEngine
->SetUpdateMode(true);
2582 void ScOutputData::DrawEditParam::adjustForRTL()
2584 if (!mpEngine
->IsRightToLeft(0))
2588 // For right-to-left, EditEngine always calculates its lines
2589 // beginning from the right edge, but EditLine::nStartPosX is
2590 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
2591 Size aLogicPaper
= mpEngine
->GetPaperSize();
2592 if ( aLogicPaper
.Width() > USHRT_MAX
)
2594 aLogicPaper
.Width() = USHRT_MAX
;
2595 mpEngine
->SetPaperSize(aLogicPaper
);
2599 void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart
, OutputDevice
* pDev
)
2601 // PDF: whole-cell hyperlink from formula?
2602 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
2603 bool bHasURL
= pPDFData
&& isHyperlinkCell();
2607 long nURLWidth
= (long) mpEngine
->CalcTextWidth();
2608 long nURLHeight
= mpEngine
->GetTextHeight();
2611 Size aPaper
= mpEngine
->GetPaperSize();
2612 if ( mbAsianVertical
)
2613 nURLHeight
= aPaper
.Height();
2615 nURLWidth
= aPaper
.Width();
2617 if (isVerticallyOriented())
2618 std::swap( nURLWidth
, nURLHeight
);
2619 else if (mbAsianVertical
)
2620 aURLStart
.X() -= nURLWidth
;
2622 Rectangle
aURLRect( aURLStart
, Size( nURLWidth
, nURLHeight
) );
2623 lcl_DoHyperlinkResult( pDev
, aURLRect
, mpCell
);
2626 void ScOutputData::DrawEditStandard(DrawEditParam
& rParam
)
2628 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
2629 OSL_ASSERT(!rParam
.mbAsianVertical
);
2631 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
2633 bool bHidden
= false;
2634 bool bRepeat
= (rParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
2635 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
2636 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
2638 if ( rParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
2640 // ignore orientation/rotation if "repeat" is active
2641 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
2644 // #i31843# "repeat" with "line breaks" is treated as default alignment
2645 // (but rotation is still disabled)
2646 if ( rParam
.mbBreak
)
2647 rParam
.meHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
2652 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2653 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2654 bHidden
= true; // gedreht wird getrennt ausgegeben
2657 SvxCellHorJustify eOutHorJust
= rParam
.meHorJust
;
2658 if (eOutHorJust
== SVX_HOR_JUSTIFY_STANDARD
)
2660 // fdo#32530: Default alignment depends on value vs string, and the
2661 // direction of the 1st letter.
2663 eOutHorJust
= rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_LEFT
: SVX_HOR_JUSTIFY_RIGHT
;
2665 eOutHorJust
= rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
2668 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
2669 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
2674 //! mirror margin values for RTL?
2675 //! move margin down to after final GetOutputArea call
2676 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2677 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
2679 SCCOL nXForPos
= rParam
.mnX
;
2680 if ( nXForPos
< nX1
)
2683 rParam
.mnPosX
= rParam
.mnInitPosX
;
2685 SCSIZE nArrYForPos
= rParam
.mnArrY
;
2686 if ( nArrYForPos
< 1 )
2689 rParam
.mnPosY
= nScrY
;
2692 OutputAreaParam aAreaParam
;
2695 // Initial page size - large for normal text, cell size for automatic line breaks
2698 Size aPaperSize
= Size( 1000000, 1000000 );
2701 // call GetOutputArea with nNeeded=0, to get only the cell width
2703 //! handle nArrY == 0
2704 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
2705 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2706 rParam
.mbCellIsValue
, true, false, aAreaParam
);
2708 //! special ScEditUtil handling if formatting for printer
2709 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
2711 if (rParam
.mbPixelToLogic
)
2713 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
2714 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
2716 // #i85342# screen display and formatting for printer,
2717 // use same GetEditArea call as in ScViewData::SetEditEngine
2719 Fraction
aFract(1,1);
2720 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
2721 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
2722 aLogicSize
.Width() = aUtilRect
.GetWidth();
2724 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
2727 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2730 // Fill the EditEngine (cell attributes and text)
2733 // default alignment for asian vertical mode is top-right
2734 if ( rParam
.mbAsianVertical
&& rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
2735 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
2737 rParam
.setPatternToEngine(mbUseStyleColor
);
2738 rParam
.setAlignmentToEngine();
2740 // Read content from cell
2742 bool bWrapFields
= false;
2743 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
2744 // Failed to read cell content. Bail out.
2748 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.mpCell
);
2749 else if ( mbUseStyleColor
&& mbForceAutoColor
)
2750 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
2752 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
2755 // Get final output area using the calculated width
2758 long nEngineWidth
, nEngineHeight
;
2759 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
2761 long nNeededPixel
= nEngineWidth
;
2762 if (rParam
.mbPixelToLogic
)
2763 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
2764 nNeededPixel
+= nLeftM
+ nRightM
;
2766 if (!rParam
.mbBreak
|| bShrink
)
2768 // for break, the first GetOutputArea call is sufficient
2769 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
2770 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2771 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
2775 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
2776 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
2777 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
2778 nEngineWidth
, nEngineHeight
, nNeededPixel
,
2779 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
2781 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
2783 // First check if twice the space for the formatted text is available
2784 // (otherwise just keep it unchanged).
2786 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
2787 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
2788 if ( nAvailable
>= 2 * nFormatted
)
2790 // "repeat" is handled with unformatted text (for performance reasons)
2791 String aCellStr
= rParam
.mpEngine
->GetText();
2792 rParam
.mpEngine
->SetText( aCellStr
);
2794 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
2795 if (rParam
.mbPixelToLogic
)
2796 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
2797 if ( pFmtDevice
!= mpRefDevice
)
2799 if ( nRepeatSize
> 0 )
2801 long nRepeatCount
= nAvailable
/ nRepeatSize
;
2802 if ( nRepeatCount
> 1 )
2804 String aRepeated
= aCellStr
;
2805 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
2806 aRepeated
.Append( aCellStr
);
2807 rParam
.mpEngine
->SetText( aRepeated
);
2809 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
2810 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2811 if (rParam
.mbPixelToLogic
)
2812 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2814 nNeededPixel
= nEngineWidth
;
2815 nNeededPixel
+= nLeftM
+ nRightM
;
2821 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
2823 rParam
.mpEngine
->SetText(rtl::OUString("###"));
2824 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2825 if (rParam
.mbPixelToLogic
)
2826 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2828 nNeededPixel
= nEngineWidth
;
2829 nNeededPixel
+= nLeftM
+ nRightM
;
2831 // No clip marks if "###" doesn't fit (same as in DrawStrings)
2834 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
2836 aPaperSize
.Width() = nNeededPixel
+ 1;
2837 if (rParam
.mbPixelToLogic
)
2838 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
2840 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2844 long nStartX
= aAreaParam
.maAlignRect
.Left();
2845 long nStartY
= aAreaParam
.maAlignRect
.Top();
2846 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
2847 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
2848 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
2852 // text with automatic breaks is aligned only within the
2853 // edit engine's paper size, the output of the whole area
2854 // is always left-aligned
2860 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
2861 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
2862 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
2863 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
2868 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
2872 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
2874 aAreaParam
.maClipRect
.Left() = nScrX
;
2875 aAreaParam
.mbLeftClip
= true;
2877 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
2879 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
2880 aAreaParam
.mbRightClip
= true;
2883 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
2884 bool bSimClip
= false;
2888 // Fields in a cell with automatic breaks: clip to cell width
2892 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
2894 aAreaParam
.maClipRect
.Top() = nScrY
;
2897 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
2899 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
2903 Size aCellSize
; // output area, excluding margins, in logical units
2904 if (rParam
.mbPixelToLogic
)
2905 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
2907 aCellSize
= Size( nOutWidth
, nOutHeight
);
2909 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
2911 const ScMergeAttr
* pMerge
=
2912 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
2913 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
2915 // Don't clip for text height when printing rows with optimal height,
2916 // except when font size is from conditional formatting.
2917 //! Allow clipping when vertically merged?
2918 if ( eType
!= OUTTYPE_PRINTER
||
2919 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
2920 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
2921 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
2926 // Show clip marks if height is at least 5pt too small and
2927 // there are several lines of text.
2928 // Not for asian vertical text, because that would interfere
2929 // with the default right position of the text.
2930 // Only with automatic line breaks, to avoid having to find
2931 // the cells with the horizontal end of the text again.
2932 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
2933 rParam
.mbBreak
&& bMarkClipped
&&
2934 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
2936 CellInfo
* pClipMarkCell
= NULL
;
2939 // anywhere in the merged area...
2940 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
2941 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
2944 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
2946 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
2949 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
2950 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
2951 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
2955 Rectangle aLogicClip
;
2956 if (bClip
|| bSimClip
)
2958 // Clip marks are already handled in GetOutputArea
2960 if (rParam
.mbPixelToLogic
)
2961 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
2963 aLogicClip
= aAreaParam
.maClipRect
;
2965 if (bClip
) // bei bSimClip nur aClipRect initialisieren
2970 mpDev
->IntersectClipRegion( aLogicClip
);
2973 mpDev
->SetClipRegion( Region( aLogicClip
) );
2978 if (rParam
.mbPixelToLogic
)
2979 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
2981 aLogicStart
= Point(nStartX
, nStartY
);
2983 if (!rParam
.mbBreak
)
2985 // horizontal alignment
2986 if (rParam
.adjustHorAlignment(rParam
.mpEngine
))
2987 // reset adjustment for the next cell
2988 rParam
.mpOldPattern
= NULL
;
2991 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
2992 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
2994 //! if pRefDevice != pFmtDevice, keep heights in logic units,
2995 //! only converting margin?
2997 if (rParam
.mbPixelToLogic
)
2998 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
2999 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3000 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
3003 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
3005 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
3007 if (rParam
.mbPixelToLogic
)
3008 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
3009 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3010 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
3013 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
3017 if (rParam
.mbPixelToLogic
)
3018 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3020 aLogicStart
.Y() += nTopM
;
3023 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3025 rParam
.adjustForRTL();
3027 // bMoveClipped handling has been replaced by complete alignment
3028 // handling (also extending to the left).
3032 // kein hartes Clipping, aber nur die betroffenen
3035 Point aDocStart
= aLogicClip
.TopLeft();
3036 aDocStart
-= aLogicStart
;
3037 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
3041 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
3049 mpDev
->SetClipRegion();
3052 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3055 void ScOutputData::DrawEditBottomTop(DrawEditParam
& rParam
)
3057 OSL_ASSERT(rParam
.meHorJust
!= SVX_HOR_JUSTIFY_REPEAT
);
3058 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3060 bool bRepeat
= (rParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3061 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3063 SvxCellHorJustify eOutHorJust
=
3064 ( rParam
.meHorJust
!= SVX_HOR_JUSTIFY_STANDARD
) ? rParam
.meHorJust
:
3065 ( rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
);
3067 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
3068 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
3070 //! mirror margin values for RTL?
3071 //! move margin down to after final GetOutputArea call
3072 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3073 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3075 SCCOL nXForPos
= rParam
.mnX
;
3076 if ( nXForPos
< nX1
)
3079 rParam
.mnPosX
= rParam
.mnInitPosX
;
3081 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3082 if ( nArrYForPos
< 1 )
3085 rParam
.mnPosY
= nScrY
;
3088 OutputAreaParam aAreaParam
;
3091 // Initial page size - large for normal text, cell size for automatic line breaks
3094 Size aPaperSize
= Size( 1000000, 1000000 );
3097 // call GetOutputArea with nNeeded=0, to get only the cell width
3099 //! handle nArrY == 0
3100 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3101 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3102 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3104 //! special ScEditUtil handling if formatting for printer
3105 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3107 if (rParam
.mbPixelToLogic
)
3109 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3110 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3113 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3116 // Fill the EditEngine (cell attributes and text)
3119 rParam
.setPatternToEngine(mbUseStyleColor
);
3120 rParam
.setAlignmentToEngine();
3122 // Read content from cell
3124 bool bWrapFields
= false;
3125 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3126 // Failed to read cell content. Bail out.
3130 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.mpCell
);
3131 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3132 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3134 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3137 // Get final output area using the calculated width
3140 long nEngineWidth
, nEngineHeight
;
3141 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3143 long nNeededPixel
= nEngineWidth
;
3144 if (rParam
.mbPixelToLogic
)
3145 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3146 nNeededPixel
+= nLeftM
+ nRightM
;
3148 if (!rParam
.mbBreak
|| bShrink
)
3150 // for break, the first GetOutputArea call is sufficient
3151 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3152 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3153 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3157 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3158 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3159 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3160 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3161 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3163 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3165 // First check if twice the space for the formatted text is available
3166 // (otherwise just keep it unchanged).
3168 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3169 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3170 if ( nAvailable
>= 2 * nFormatted
)
3172 // "repeat" is handled with unformatted text (for performance reasons)
3173 String aCellStr
= rParam
.mpEngine
->GetText();
3174 rParam
.mpEngine
->SetText( aCellStr
);
3176 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
3177 if (rParam
.mbPixelToLogic
)
3178 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3179 if ( pFmtDevice
!= mpRefDevice
)
3181 if ( nRepeatSize
> 0 )
3183 long nRepeatCount
= nAvailable
/ nRepeatSize
;
3184 if ( nRepeatCount
> 1 )
3186 String aRepeated
= aCellStr
;
3187 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3188 aRepeated
.Append( aCellStr
);
3189 rParam
.mpEngine
->SetText( aRepeated
);
3191 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3192 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3193 if (rParam
.mbPixelToLogic
)
3194 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3196 nNeededPixel
= nEngineWidth
;
3197 nNeededPixel
+= nLeftM
+ nRightM
;
3203 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3205 rParam
.mpEngine
->SetText(rtl::OUString("###"));
3206 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3207 if (rParam
.mbPixelToLogic
)
3208 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3210 nNeededPixel
= nEngineWidth
;
3211 nNeededPixel
+= nLeftM
+ nRightM
;
3213 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3217 long nStartX
= aAreaParam
.maAlignRect
.Left();
3218 long nStartY
= aAreaParam
.maAlignRect
.Top();
3219 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3220 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3221 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3225 // text with automatic breaks is aligned only within the
3226 // edit engine's paper size, the output of the whole area
3227 // is always left-aligned
3233 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3234 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3235 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3236 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3241 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3245 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3247 aAreaParam
.maClipRect
.Left() = nScrX
;
3248 aAreaParam
.mbLeftClip
= true;
3250 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3252 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3253 aAreaParam
.mbRightClip
= true;
3256 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3257 bool bSimClip
= false;
3261 // Fields in a cell with automatic breaks: clip to cell width
3265 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3267 aAreaParam
.maClipRect
.Top() = nScrY
;
3270 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3272 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3276 Size aCellSize
; // output area, excluding margins, in logical units
3277 if (rParam
.mbPixelToLogic
)
3278 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
3280 aCellSize
= Size( nOutWidth
, nOutHeight
);
3282 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
3284 const ScMergeAttr
* pMerge
=
3285 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
3286 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
3288 // Don't clip for text height when printing rows with optimal height,
3289 // except when font size is from conditional formatting.
3290 //! Allow clipping when vertically merged?
3291 if ( eType
!= OUTTYPE_PRINTER
||
3292 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
3293 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
3294 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
3299 // Show clip marks if height is at least 5pt too small and
3300 // there are several lines of text.
3301 // Not for asian vertical text, because that would interfere
3302 // with the default right position of the text.
3303 // Only with automatic line breaks, to avoid having to find
3304 // the cells with the horizontal end of the text again.
3305 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
3306 rParam
.mbBreak
&& bMarkClipped
&&
3307 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3309 CellInfo
* pClipMarkCell
= NULL
;
3312 // anywhere in the merged area...
3313 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3314 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3317 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3319 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3322 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
3323 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3324 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3328 Rectangle aLogicClip
;
3329 if (bClip
|| bSimClip
)
3331 // Clip marks are already handled in GetOutputArea
3333 if (rParam
.mbPixelToLogic
)
3334 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3336 aLogicClip
= aAreaParam
.maClipRect
;
3338 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3343 mpDev
->IntersectClipRegion( aLogicClip
);
3346 mpDev
->SetClipRegion( Region( aLogicClip
) );
3350 Point
aLogicStart(nStartX
, nStartY
);
3351 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3353 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3355 if (rParam
.meHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| rParam
.mbBreak
)
3357 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3358 aPSize
.Width() = aCellSize
.Height();
3359 rParam
.mpEngine
->SetPaperSize(aPSize
);
3361 rParam
.mbBreak
? aPSize
.Width() : nEngineHeight
;
3365 // Note that the "paper" is rotated 90 degrees to the left, so
3366 // paper's width is in vertical direction. Also, the whole text
3367 // is on a single line, as text wrap is not in effect.
3369 // Set the paper width to be the width of the text.
3370 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3371 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3372 rParam
.mpEngine
->SetPaperSize(aPSize
);
3375 long nTopOffset
= 0;
3376 if (rParam
.mbPixelToLogic
)
3378 nGap
= mpRefDevice
->LogicToPixel(aCellSize
).Height() - mpRefDevice
->LogicToPixel(aPSize
).Width();
3379 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3380 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3384 nGap
= aCellSize
.Height() - aPSize
.Width();
3388 // First, align text to bottom.
3389 aLogicStart
.Y() += aCellSize
.Height();
3390 aLogicStart
.Y() += nTopOffset
;
3392 switch (rParam
.meVerJust
)
3394 case SVX_VER_JUSTIFY_STANDARD
:
3395 case SVX_VER_JUSTIFY_BOTTOM
:
3396 // align to bottom (do nothing).
3398 case SVX_VER_JUSTIFY_CENTER
:
3400 aLogicStart
.Y() -= nGap
/ 2;
3402 case SVX_VER_JUSTIFY_BLOCK
:
3403 case SVX_VER_JUSTIFY_TOP
:
3405 aLogicStart
.Y() -= nGap
;
3411 rParam
.adjustForRTL();
3412 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 900);
3419 mpDev
->SetClipRegion();
3422 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3425 void ScOutputData::DrawEditTopBottom(DrawEditParam
& rParam
)
3427 OSL_ASSERT(rParam
.meHorJust
!= SVX_HOR_JUSTIFY_REPEAT
);
3428 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3430 bool bRepeat
= (rParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3431 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3433 SvxCellHorJustify eOutHorJust
=
3434 ( rParam
.meHorJust
!= SVX_HOR_JUSTIFY_STANDARD
) ? rParam
.meHorJust
:
3435 ( rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
);
3437 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
3438 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
3440 //! mirror margin values for RTL?
3441 //! move margin down to after final GetOutputArea call
3442 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3443 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3445 SCCOL nXForPos
= rParam
.mnX
;
3446 if ( nXForPos
< nX1
)
3449 rParam
.mnPosX
= rParam
.mnInitPosX
;
3451 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3452 if ( nArrYForPos
< 1 )
3455 rParam
.mnPosY
= nScrY
;
3458 OutputAreaParam aAreaParam
;
3461 // Initial page size - large for normal text, cell size for automatic line breaks
3464 Size aPaperSize
= Size( 1000000, 1000000 );
3465 if (rParam
.hasLineBreak())
3467 // call GetOutputArea with nNeeded=0, to get only the cell width
3469 //! handle nArrY == 0
3470 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3471 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3472 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3474 //! special ScEditUtil handling if formatting for printer
3475 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3477 if (rParam
.mbPixelToLogic
)
3479 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3480 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3483 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3486 // Fill the EditEngine (cell attributes and text)
3489 rParam
.setPatternToEngine(mbUseStyleColor
);
3490 rParam
.setAlignmentToEngine();
3492 // Read content from cell
3494 bool bWrapFields
= false;
3495 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3496 // Failed to read cell content. Bail out.
3500 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.mpCell
);
3501 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3502 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3504 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3507 // Get final output area using the calculated width
3510 long nEngineWidth
, nEngineHeight
;
3511 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3513 long nNeededPixel
= nEngineWidth
;
3514 if (rParam
.mbPixelToLogic
)
3515 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3516 nNeededPixel
+= nLeftM
+ nRightM
;
3518 if (!rParam
.mbBreak
|| bShrink
)
3520 // for break, the first GetOutputArea call is sufficient
3521 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3522 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3523 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3527 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3528 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3529 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3530 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3531 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3533 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3535 // First check if twice the space for the formatted text is available
3536 // (otherwise just keep it unchanged).
3538 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3539 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3540 if ( nAvailable
>= 2 * nFormatted
)
3542 // "repeat" is handled with unformatted text (for performance reasons)
3543 String aCellStr
= rParam
.mpEngine
->GetText();
3544 rParam
.mpEngine
->SetText( aCellStr
);
3546 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
3547 if (rParam
.mbPixelToLogic
)
3548 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3549 if ( pFmtDevice
!= mpRefDevice
)
3551 if ( nRepeatSize
> 0 )
3553 long nRepeatCount
= nAvailable
/ nRepeatSize
;
3554 if ( nRepeatCount
> 1 )
3556 String aRepeated
= aCellStr
;
3557 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3558 aRepeated
.Append( aCellStr
);
3559 rParam
.mpEngine
->SetText( aRepeated
);
3561 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3562 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3563 if (rParam
.mbPixelToLogic
)
3564 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3566 nNeededPixel
= nEngineWidth
;
3567 nNeededPixel
+= nLeftM
+ nRightM
;
3573 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3575 rParam
.mpEngine
->SetText(rtl::OUString("###"));
3576 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3577 if (rParam
.mbPixelToLogic
)
3578 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3580 nNeededPixel
= nEngineWidth
;
3581 nNeededPixel
+= nLeftM
+ nRightM
;
3583 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3587 long nStartX
= aAreaParam
.maAlignRect
.Left();
3588 long nStartY
= aAreaParam
.maAlignRect
.Top();
3589 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3590 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3591 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3595 // text with automatic breaks is aligned only within the
3596 // edit engine's paper size, the output of the whole area
3597 // is always left-aligned
3600 if (rParam
.meHorJust
== SVX_HOR_JUSTIFY_BLOCK
)
3601 nStartX
+= aPaperSize
.Height();
3605 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3606 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3607 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3608 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3613 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3617 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3619 aAreaParam
.maClipRect
.Left() = nScrX
;
3620 aAreaParam
.mbLeftClip
= true;
3622 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3624 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3625 aAreaParam
.mbRightClip
= true;
3628 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3629 bool bSimClip
= false;
3633 // Fields in a cell with automatic breaks: clip to cell width
3637 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3639 aAreaParam
.maClipRect
.Top() = nScrY
;
3642 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3644 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3648 Size aCellSize
; // output area, excluding margins, in logical units
3649 if (rParam
.mbPixelToLogic
)
3650 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
3652 aCellSize
= Size( nOutWidth
, nOutHeight
);
3654 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
3656 const ScMergeAttr
* pMerge
=
3657 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
3658 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
3660 // Don't clip for text height when printing rows with optimal height,
3661 // except when font size is from conditional formatting.
3662 //! Allow clipping when vertically merged?
3663 if ( eType
!= OUTTYPE_PRINTER
||
3664 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
3665 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
3666 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
3671 // Show clip marks if height is at least 5pt too small and
3672 // there are several lines of text.
3673 // Not for asian vertical text, because that would interfere
3674 // with the default right position of the text.
3675 // Only with automatic line breaks, to avoid having to find
3676 // the cells with the horizontal end of the text again.
3677 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
3678 rParam
.mbBreak
&& bMarkClipped
&&
3679 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3681 CellInfo
* pClipMarkCell
= NULL
;
3684 // anywhere in the merged area...
3685 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3686 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3689 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3691 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3694 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
3695 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3696 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3700 Rectangle aLogicClip
;
3701 if (bClip
|| bSimClip
)
3703 // Clip marks are already handled in GetOutputArea
3705 if (rParam
.mbPixelToLogic
)
3706 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3708 aLogicClip
= aAreaParam
.maClipRect
;
3710 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3715 mpDev
->IntersectClipRegion( aLogicClip
);
3718 mpDev
->SetClipRegion( Region( aLogicClip
) );
3722 Point
aLogicStart(nStartX
, nStartY
);
3723 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3725 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3727 if (rParam
.meHorJust
!= SVX_HOR_JUSTIFY_BLOCK
)
3729 aLogicStart
.X() += nEngineWidth
;
3730 if (!rParam
.mbBreak
)
3732 // Set the paper width to text size.
3733 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3734 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3735 rParam
.mpEngine
->SetPaperSize(aPSize
);
3738 long nTopOffset
= 0; // offset by top margin
3739 if (rParam
.mbPixelToLogic
)
3741 nGap
= mpRefDevice
->LogicToPixel(aPSize
).Width() - mpRefDevice
->LogicToPixel(aCellSize
).Height();
3742 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3743 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3747 nGap
= aPSize
.Width() - aCellSize
.Height();
3750 aLogicStart
.Y() += nTopOffset
;
3752 switch (rParam
.meVerJust
)
3754 case SVX_VER_JUSTIFY_STANDARD
:
3755 case SVX_VER_JUSTIFY_BOTTOM
:
3757 aLogicStart
.Y() -= nGap
;
3759 case SVX_VER_JUSTIFY_CENTER
:
3761 aLogicStart
.Y() -= nGap
/ 2;
3763 case SVX_VER_JUSTIFY_BLOCK
:
3764 case SVX_VER_JUSTIFY_TOP
:
3765 // align to top (do nothing)
3772 rParam
.adjustForRTL();
3774 // bMoveClipped handling has been replaced by complete alignment
3775 // handling (also extending to the left).
3777 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 2700);
3784 mpDev
->SetClipRegion();
3787 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3790 void ScOutputData::DrawEditStacked(DrawEditParam
& rParam
)
3792 OSL_ASSERT(rParam
.meHorJust
!= SVX_HOR_JUSTIFY_REPEAT
);
3793 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3795 bool bRepeat
= (rParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3796 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3798 rParam
.mbAsianVertical
=
3799 lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_VERTICAL_ASIAN
, rParam
.mpCondSet
);
3801 if ( rParam
.mbAsianVertical
)
3803 // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
3804 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
3805 DrawEditAsianVertical(rParam
);
3809 SvxCellHorJustify eOutHorJust
=
3810 ( rParam
.meHorJust
!= SVX_HOR_JUSTIFY_STANDARD
) ? rParam
.meHorJust
:
3811 ( rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
);
3813 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
3814 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
3816 //! mirror margin values for RTL?
3817 //! move margin down to after final GetOutputArea call
3818 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3819 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3821 SCCOL nXForPos
= rParam
.mnX
;
3822 if ( nXForPos
< nX1
)
3825 rParam
.mnPosX
= rParam
.mnInitPosX
;
3827 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3828 if ( nArrYForPos
< 1 )
3831 rParam
.mnPosY
= nScrY
;
3834 OutputAreaParam aAreaParam
;
3837 // Initial page size - large for normal text, cell size for automatic line breaks
3840 Size aPaperSize
= Size( 1000000, 1000000 );
3841 // call GetOutputArea with nNeeded=0, to get only the cell width
3843 //! handle nArrY == 0
3844 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3845 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3846 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3848 //! special ScEditUtil handling if formatting for printer
3849 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3851 if (rParam
.mbPixelToLogic
)
3853 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3854 if ( rParam
.mbBreak
&& mpRefDevice
!= pFmtDevice
)
3856 // #i85342# screen display and formatting for printer,
3857 // use same GetEditArea call as in ScViewData::SetEditEngine
3859 Fraction
aFract(1,1);
3860 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
3861 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
3862 aLogicSize
.Width() = aUtilRect
.GetWidth();
3864 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3867 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3870 // Fill the EditEngine (cell attributes and text)
3873 rParam
.setPatternToEngine(mbUseStyleColor
);
3874 rParam
.setAlignmentToEngine();
3876 // Read content from cell
3878 bool bWrapFields
= false;
3879 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3880 // Failed to read cell content. Bail out.
3884 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.mpCell
);
3885 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3886 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3888 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3891 // Get final output area using the calculated width
3894 long nEngineWidth
, nEngineHeight
;
3895 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3897 long nNeededPixel
= nEngineWidth
;
3898 if (rParam
.mbPixelToLogic
)
3899 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3900 nNeededPixel
+= nLeftM
+ nRightM
;
3904 // for break, the first GetOutputArea call is sufficient
3905 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3906 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3907 true, false, false, aAreaParam
);
3909 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3910 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
3911 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3912 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3913 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3915 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3917 // First check if twice the space for the formatted text is available
3918 // (otherwise just keep it unchanged).
3920 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3921 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3922 if ( nAvailable
>= 2 * nFormatted
)
3924 // "repeat" is handled with unformatted text (for performance reasons)
3925 String aCellStr
= rParam
.mpEngine
->GetText();
3926 rParam
.mpEngine
->SetText( aCellStr
);
3928 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
3929 if (rParam
.mbPixelToLogic
)
3930 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3931 if ( pFmtDevice
!= mpRefDevice
)
3933 if ( nRepeatSize
> 0 )
3935 long nRepeatCount
= nAvailable
/ nRepeatSize
;
3936 if ( nRepeatCount
> 1 )
3938 String aRepeated
= aCellStr
;
3939 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3940 aRepeated
.Append( aCellStr
);
3941 rParam
.mpEngine
->SetText( aRepeated
);
3943 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3944 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3945 if (rParam
.mbPixelToLogic
)
3946 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3948 nNeededPixel
= nEngineWidth
;
3949 nNeededPixel
+= nLeftM
+ nRightM
;
3955 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3957 rParam
.mpEngine
->SetText(rtl::OUString("###"));
3958 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3959 if (rParam
.mbPixelToLogic
)
3960 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3962 nNeededPixel
= nEngineWidth
;
3963 nNeededPixel
+= nLeftM
+ nRightM
;
3965 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3968 if ( eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
3970 aPaperSize
.Width() = nNeededPixel
+ 1;
3971 if (rParam
.mbPixelToLogic
)
3972 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
3974 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3978 long nStartX
= aAreaParam
.maAlignRect
.Left();
3979 long nStartY
= aAreaParam
.maAlignRect
.Top();
3980 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3981 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3982 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3986 // text with automatic breaks is aligned only within the
3987 // edit engine's paper size, the output of the whole area
3988 // is always left-aligned
3994 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3995 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3996 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3997 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
4002 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
4006 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
4008 aAreaParam
.maClipRect
.Left() = nScrX
;
4009 aAreaParam
.mbLeftClip
= true;
4011 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
4013 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
4014 aAreaParam
.mbRightClip
= true;
4017 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
4018 bool bSimClip
= false;
4022 // Fields in a cell with automatic breaks: clip to cell width
4026 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
4028 aAreaParam
.maClipRect
.Top() = nScrY
;
4031 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
4033 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
4037 Size aCellSize
; // output area, excluding margins, in logical units
4038 if (rParam
.mbPixelToLogic
)
4039 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4041 aCellSize
= Size( nOutWidth
, nOutHeight
);
4043 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4045 const ScMergeAttr
* pMerge
=
4046 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4047 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4049 // Don't clip for text height when printing rows with optimal height,
4050 // except when font size is from conditional formatting.
4051 //! Allow clipping when vertically merged?
4052 if ( eType
!= OUTTYPE_PRINTER
||
4053 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4054 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4055 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4060 // Show clip marks if height is at least 5pt too small and
4061 // there are several lines of text.
4062 // Not for asian vertical text, because that would interfere
4063 // with the default right position of the text.
4064 // Only with automatic line breaks, to avoid having to find
4065 // the cells with the horizontal end of the text again.
4066 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4067 rParam
.mbBreak
&& bMarkClipped
&&
4068 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4070 CellInfo
* pClipMarkCell
= NULL
;
4073 // anywhere in the merged area...
4074 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4075 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4078 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4080 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4083 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4084 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4085 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4089 Rectangle aLogicClip
;
4090 if (bClip
|| bSimClip
)
4092 // Clip marks are already handled in GetOutputArea
4094 if (rParam
.mbPixelToLogic
)
4095 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4097 aLogicClip
= aAreaParam
.maClipRect
;
4099 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4104 mpDev
->IntersectClipRegion( aLogicClip
);
4107 mpDev
->SetClipRegion( Region( aLogicClip
) );
4112 if (rParam
.mbPixelToLogic
)
4113 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4115 aLogicStart
= Point(nStartX
, nStartY
);
4117 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
4118 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
4120 //! if pRefDevice != pFmtDevice, keep heights in logic units,
4121 //! only converting margin?
4123 if (rParam
.mbPixelToLogic
)
4124 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
4125 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4126 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
4129 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
4131 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
4133 if (rParam
.mbPixelToLogic
)
4134 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
4135 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4136 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
4139 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
4143 if (rParam
.mbPixelToLogic
)
4144 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4146 aLogicStart
.Y() += nTopM
;
4149 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4151 Size aPaperLogic
= rParam
.mpEngine
->GetPaperSize();
4152 aPaperLogic
.Width() = nEngineWidth
;
4153 rParam
.mpEngine
->SetPaperSize(aPaperLogic
);
4155 rParam
.adjustForRTL();
4157 // bMoveClipped handling has been replaced by complete alignment
4158 // handling (also extending to the left).
4162 // kein hartes Clipping, aber nur die betroffenen
4165 Point aDocStart
= aLogicClip
.TopLeft();
4166 aDocStart
-= aLogicStart
;
4167 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
4171 rParam
.mpEngine
->Draw( mpDev
, aLogicStart
, 0 );
4179 mpDev
->SetClipRegion();
4182 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4185 void ScOutputData::DrawEditAsianVertical(DrawEditParam
& rParam
)
4187 // When in asian vertical orientation, the orientation value is STANDARD,
4188 // and the asian vertical boolean is true.
4189 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
4190 OSL_ASSERT(rParam
.mbAsianVertical
);
4191 OSL_ASSERT(rParam
.meHorJust
!= SVX_HOR_JUSTIFY_REPEAT
);
4193 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
4195 bool bHidden
= false;
4196 bool bRepeat
= false;
4197 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
4198 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
4202 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
4203 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
4204 bHidden
= true; // gedreht wird getrennt ausgegeben
4207 // default alignment for asian vertical mode is top-right
4208 if ( rParam
.meHorJust
== SVX_HOR_JUSTIFY_STANDARD
)
4209 rParam
.meHorJust
= SVX_HOR_JUSTIFY_RIGHT
;
4211 SvxCellHorJustify eOutHorJust
=
4212 ( rParam
.meHorJust
!= SVX_HOR_JUSTIFY_STANDARD
) ? rParam
.meHorJust
:
4213 ( rParam
.mbCellIsValue
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
);
4215 if ( eOutHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eOutHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
4216 eOutHorJust
= SVX_HOR_JUSTIFY_LEFT
; // repeat is not yet implemented
4221 //! mirror margin values for RTL?
4222 //! move margin down to after final GetOutputArea call
4223 long nTopM
, nLeftM
, nBottomM
, nRightM
;
4224 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
4226 SCCOL nXForPos
= rParam
.mnX
;
4227 if ( nXForPos
< nX1
)
4230 rParam
.mnPosX
= rParam
.mnInitPosX
;
4232 SCSIZE nArrYForPos
= rParam
.mnArrY
;
4233 if ( nArrYForPos
< 1 )
4236 rParam
.mnPosY
= nScrY
;
4239 OutputAreaParam aAreaParam
;
4242 // Initial page size - large for normal text, cell size for automatic line breaks
4245 Size aPaperSize
= Size( 1000000, 1000000 );
4246 // call GetOutputArea with nNeeded=0, to get only the cell width
4248 //! handle nArrY == 0
4249 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
4250 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4251 rParam
.mbCellIsValue
, true, false, aAreaParam
);
4253 //! special ScEditUtil handling if formatting for printer
4254 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
4256 if (rParam
.mbPixelToLogic
)
4258 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
4259 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
4261 // #i85342# screen display and formatting for printer,
4262 // use same GetEditArea call as in ScViewData::SetEditEngine
4264 Fraction
aFract(1,1);
4265 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
4266 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
4267 aLogicSize
.Width() = aUtilRect
.GetWidth();
4269 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
4272 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4275 // Fill the EditEngine (cell attributes and text)
4278 // default alignment for asian vertical mode is top-right
4279 if ( rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
4280 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
4282 rParam
.setPatternToEngine(mbUseStyleColor
);
4283 rParam
.setAlignmentToEngine();
4285 // Read content from cell
4287 bool bWrapFields
= false;
4288 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
4289 // Failed to read cell content. Bail out.
4293 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.mpCell
);
4294 else if ( mbUseStyleColor
&& mbForceAutoColor
)
4295 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
4297 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
4300 // Get final output area using the calculated width
4303 long nEngineWidth
, nEngineHeight
;
4304 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
4306 long nNeededPixel
= nEngineWidth
;
4307 if (rParam
.mbPixelToLogic
)
4308 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
4309 nNeededPixel
+= nLeftM
+ nRightM
;
4311 // for break, the first GetOutputArea call is sufficient
4312 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
4313 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4314 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
4318 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
4319 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
4320 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
4321 nEngineWidth
, nEngineHeight
, nNeededPixel
,
4322 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
4324 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
4326 // First check if twice the space for the formatted text is available
4327 // (otherwise just keep it unchanged).
4329 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
4330 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
4331 if ( nAvailable
>= 2 * nFormatted
)
4333 // "repeat" is handled with unformatted text (for performance reasons)
4334 String aCellStr
= rParam
.mpEngine
->GetText();
4335 rParam
.mpEngine
->SetText( aCellStr
);
4337 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
4338 if (rParam
.mbPixelToLogic
)
4339 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
4340 if ( pFmtDevice
!= mpRefDevice
)
4342 if ( nRepeatSize
> 0 )
4344 long nRepeatCount
= nAvailable
/ nRepeatSize
;
4345 if ( nRepeatCount
> 1 )
4347 String aRepeated
= aCellStr
;
4348 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
4349 aRepeated
.Append( aCellStr
);
4350 rParam
.mpEngine
->SetText( aRepeated
);
4352 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
4353 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
4354 if (rParam
.mbPixelToLogic
)
4355 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
4357 nNeededPixel
= nEngineWidth
;
4358 nNeededPixel
+= nLeftM
+ nRightM
;
4364 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
4366 rParam
.mpEngine
->SetText(rtl::OUString("###"));
4367 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
4368 if (rParam
.mbPixelToLogic
)
4369 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
4371 nNeededPixel
= nEngineWidth
;
4372 nNeededPixel
+= nLeftM
+ nRightM
;
4374 // No clip marks if "###" doesn't fit (same as in DrawStrings)
4377 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
4379 aPaperSize
.Width() = nNeededPixel
+ 1;
4380 if (rParam
.mbPixelToLogic
)
4381 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4383 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4386 long nStartX
= aAreaParam
.maAlignRect
.Left();
4387 long nStartY
= aAreaParam
.maAlignRect
.Top();
4388 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
4389 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
4390 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
4392 // text with automatic breaks is aligned only within the
4393 // edit engine's paper size, the output of the whole area
4394 // is always left-aligned
4398 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
4402 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
4404 aAreaParam
.maClipRect
.Left() = nScrX
;
4405 aAreaParam
.mbLeftClip
= true;
4407 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
4409 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
4410 aAreaParam
.mbRightClip
= true;
4413 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
4414 bool bSimClip
= false;
4418 // Fields in a cell with automatic breaks: clip to cell width
4422 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
4424 aAreaParam
.maClipRect
.Top() = nScrY
;
4427 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
4429 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
4433 Size aCellSize
; // output area, excluding margins, in logical units
4434 if (rParam
.mbPixelToLogic
)
4435 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4437 aCellSize
= Size( nOutWidth
, nOutHeight
);
4439 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4441 const ScMergeAttr
* pMerge
=
4442 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4443 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4445 // Don't clip for text height when printing rows with optimal height,
4446 // except when font size is from conditional formatting.
4447 //! Allow clipping when vertically merged?
4448 if ( eType
!= OUTTYPE_PRINTER
||
4449 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4450 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4451 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4456 // Show clip marks if height is at least 5pt too small and
4457 // there are several lines of text.
4458 // Not for asian vertical text, because that would interfere
4459 // with the default right position of the text.
4460 // Only with automatic line breaks, to avoid having to find
4461 // the cells with the horizontal end of the text again.
4462 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4463 ( rParam
.mbBreak
|| rParam
.meOrient
== SVX_ORIENTATION_STACKED
) &&
4464 !rParam
.mbAsianVertical
&& bMarkClipped
&&
4465 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4467 CellInfo
* pClipMarkCell
= NULL
;
4470 // anywhere in the merged area...
4471 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4472 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4475 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4477 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4480 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4481 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4482 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4486 Rectangle aLogicClip
;
4487 if (bClip
|| bSimClip
)
4489 // Clip marks are already handled in GetOutputArea
4491 if (rParam
.mbPixelToLogic
)
4492 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4494 aLogicClip
= aAreaParam
.maClipRect
;
4496 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4501 mpDev
->IntersectClipRegion( aLogicClip
);
4504 mpDev
->SetClipRegion( Region( aLogicClip
) );
4509 if (rParam
.mbPixelToLogic
)
4510 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4512 aLogicStart
= Point(nStartX
, nStartY
);
4514 long nAvailWidth
= aCellSize
.Width();
4515 // space for AutoFilter is already handled in GetOutputArea
4517 // horizontal alignment
4519 if (rParam
.meHorJust
==SVX_HOR_JUSTIFY_RIGHT
)
4520 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
4521 else if (rParam
.meHorJust
==SVX_HOR_JUSTIFY_CENTER
)
4522 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
4524 // paper size is subtracted below
4525 aLogicStart
.X() += nEngineWidth
;
4527 // vertical adjustment is within the EditEngine
4528 if (rParam
.mbPixelToLogic
)
4529 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4531 aLogicStart
.Y() += nTopM
;
4533 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4535 rParam
.adjustForRTL();
4537 // bMoveClipped handling has been replaced by complete alignment
4538 // handling (also extending to the left).
4540 // with SetVertical, the start position is top left of
4541 // the whole output area, not the text itself
4542 aLogicStart
.X() -= rParam
.mpEngine
->GetPaperSize().Width();
4544 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
4551 mpDev
->SetClipRegion();
4554 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4557 void ScOutputData::DrawEdit(sal_Bool bPixelToLogic
)
4559 ScFieldEditEngine
* pEngine
= NULL
;
4560 bool bHyphenatorSet
= false;
4561 const ScPatternAttr
* pOldPattern
= NULL
;
4562 const SfxItemSet
* pOldCondSet
= NULL
;
4563 ScBaseCell
* pCell
= NULL
;
4565 long nInitPosX
= nScrX
;
4568 nInitPosX
+= nMirrorW
- 1;
4570 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4572 //! store nLastContentCol as member!
4573 SCCOL nLastContentCol
= MAXCOL
;
4575 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
4576 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
4578 long nRowPosY
= nScrY
;
4579 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4581 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4583 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4585 if ( pThisRowInfo
->bChanged
|| nArrY
==0 )
4588 for (SCCOL nX
=0; nX
<=nX2
; nX
++) // wegen Ueberhaengen
4590 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4592 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4593 if (pInfo
->bEditEngine
)
4595 SCROW nY
= pThisRowInfo
->nRowNo
;
4597 SCCOL nCellX
= nX
; // position where the cell really starts
4599 sal_Bool bDoCell
= false;
4601 long nPosY
= nRowPosY
;
4605 nY
= pRowInfo
[1].nRowNo
;
4606 SCCOL nOverX
; // start of the merged cells
4608 if (GetMergeOrigin( nX
,nY
, 1, nOverX
,nOverY
, sal_True
))
4615 else if ( nX
== nX2
&& !pThisRowInfo
->pCellInfo
[nX
+1].pCell
)
4617 // Rest of a long text further to the right?
4620 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
4624 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
4625 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
4636 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
4639 const ScPatternAttr
* pPattern
= NULL
;
4640 const SfxItemSet
* pCondSet
= NULL
;
4643 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
&&
4644 !mpDoc
->ColHidden(nCellX
, nTab
) )
4646 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
4647 pPattern
= rCellInfo
.pPatternAttr
;
4648 pCondSet
= rCellInfo
.pConditionSet
;
4649 pCell
= rCellInfo
.pCell
;
4651 else // get from document
4653 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
4654 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
4655 GetVisibleCell( nCellX
, nCellY
, nTab
, pCell
);
4663 pEngine
= CreateOutputEditEngine();
4665 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4667 // fdo#32530: Check if the first character is RTL.
4668 rtl::OUString aStr
= mpDoc
->GetString(nCellX
, nCellY
, nTab
);
4670 DrawEditParam
aParam(pPattern
, pCondSet
, lcl_SafeIsValue(pCell
));
4671 aParam
.mbPixelToLogic
= bPixelToLogic
;
4672 aParam
.mbHyphenatorSet
= bHyphenatorSet
;
4673 aParam
.mbRTL
= beginsWithRTLCharacter(aStr
);
4674 aParam
.mpEngine
= pEngine
;
4675 aParam
.mpCell
= pCell
;
4676 aParam
.mnArrY
= nArrY
;
4679 aParam
.mnCellX
= nCellX
;
4680 aParam
.mnCellY
= nCellY
;
4681 aParam
.mnPosX
= nPosX
;
4682 aParam
.mnPosY
= nPosY
;
4683 aParam
.mnInitPosX
= nInitPosX
;
4684 aParam
.mpOldPattern
= pOldPattern
;
4685 aParam
.mpOldCondSet
= pOldCondSet
;
4686 aParam
.mpThisRowInfo
= pThisRowInfo
;
4687 if (aParam
.meHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
4689 // ignore orientation/rotation if "repeat" is active
4690 aParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
4692 switch (aParam
.meOrient
)
4694 case SVX_ORIENTATION_BOTTOMTOP
:
4695 DrawEditBottomTop(aParam
);
4697 case SVX_ORIENTATION_TOPBOTTOM
:
4698 DrawEditTopBottom(aParam
);
4700 case SVX_ORIENTATION_STACKED
:
4701 // this can be vertically stacked or asian vertical.
4702 DrawEditStacked(aParam
);
4705 DrawEditStandard(aParam
);
4708 // Retrieve parameters for next iteration.
4709 pOldPattern
= aParam
.mpOldPattern
;
4710 pOldCondSet
= aParam
.mpOldCondSet
;
4711 bHyphenatorSet
= aParam
.mbHyphenatorSet
;
4714 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
4717 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
4723 DrawRotated(bPixelToLogic
); //! von aussen rufen ?
4726 // -------------------------------------------------------------------------------
4728 void ScOutputData::DrawRotated(sal_Bool bPixelToLogic
)
4730 //! nRotMax speichern
4731 SCCOL nRotMax
= nX2
;
4732 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
4733 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
4734 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
4737 ScModule
* pScMod
= SC_MOD();
4738 sal_Int32 nConfBackColor
= pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
4739 sal_Bool bCellContrast
= mbUseStyleColor
&&
4740 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
4742 ScFieldEditEngine
* pEngine
= NULL
;
4743 sal_Bool bHyphenatorSet
= false;
4744 const ScPatternAttr
* pPattern
;
4745 const SfxItemSet
* pCondSet
;
4746 const ScPatternAttr
* pOldPattern
= NULL
;
4747 const SfxItemSet
* pOldCondSet
= NULL
;
4748 ScBaseCell
* pCell
= NULL
;
4750 long nInitPosX
= nScrX
;
4753 nInitPosX
+= nMirrorW
- 1;
4755 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4757 long nRowPosY
= nScrY
;
4758 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4760 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4761 long nCellHeight
= (long) pThisRowInfo
->nHeight
;
4762 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4764 if ( ( pThisRowInfo
->bChanged
|| nArrY
==0 ) && pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
)
4767 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
4769 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4771 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4772 if ( pInfo
->nRotateDir
!= SC_ROTDIR_NONE
)
4774 SCROW nY
= pThisRowInfo
->nRowNo
;
4776 sal_Bool bHidden
= false;
4778 if ( nX
== nEditCol
&& nY
== nEditRow
)
4784 pEngine
= CreateOutputEditEngine();
4786 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4788 long nPosY
= nRowPosY
;
4789 sal_Bool bVisChanged
= false;
4791 //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
4793 sal_Bool bFromDoc
= false;
4794 pPattern
= pInfo
->pPatternAttr
;
4795 pCondSet
= pInfo
->pConditionSet
;
4798 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
4799 bFromDoc
= sal_True
;
4801 pCell
= pInfo
->pCell
;
4803 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
4805 if (!pCell
&& nX
>nX2
)
4806 GetVisibleCell( nX
, nY
, nTab
, pCell
);
4808 if ( !pCell
|| IsEmptyCellText( pThisRowInfo
, nX
, nY
) )
4809 bHidden
= sal_True
; // nRotateDir is also set without a cell
4811 long nCellWidth
= (long) pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
4813 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)
4814 pPattern
->GetItem(ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
4815 sal_Bool bBreak
= ( eHorJust
== SVX_HOR_JUSTIFY_BLOCK
) ||
4816 ((const SfxBoolItem
&)pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue();
4817 sal_Bool bRepeat
= ( eHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !bBreak
);
4818 sal_Bool bShrink
= !bBreak
&& !bRepeat
&& static_cast<const SfxBoolItem
&>
4819 (pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
4820 SvxCellOrientation eOrient
= pPattern
->GetCellOrientation( pCondSet
);
4822 const ScMergeAttr
* pMerge
=
4823 (ScMergeAttr
*)&pPattern
->GetItem(ATTR_MERGE
);
4824 sal_Bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4826 long nStartX
= nPosX
;
4827 long nStartY
= nPosY
;
4830 if ((bBreak
|| eOrient
!=SVX_ORIENTATION_STANDARD
) && !bMerged
)
4834 nStartX
= nInitPosX
;
4839 nStartX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
4843 long nCellStartX
= nStartX
;
4845 // Ersatzdarstellung fuer zu kleinen Text weggelassen
4849 long nOutWidth
= nCellWidth
- 1;
4850 long nOutHeight
= nCellHeight
;
4852 if ( bMerged
) // Zusammengefasst
4854 SCCOL nCountX
= pMerge
->GetColMerge();
4855 for (SCCOL i
=1; i
<nCountX
; i
++)
4856 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nX
+i
,nTab
) * mnPPTX
);
4857 SCROW nCountY
= pMerge
->GetRowMerge();
4858 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nY
+1, nY
+nCountY
-1, nTab
, mnPPTY
);
4861 SvxCellVerJustify eVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)
4862 pPattern
->GetItem(ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
4864 // Syntax-Modus wird hier ignoriert...
4866 // StringDiffer doesn't look at hyphenate, language items
4867 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
)
4869 SfxItemSet
* pSet
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
4870 pPattern
->FillEditItemSet( pSet
, pCondSet
);
4872 // Ausrichtung fuer EditEngine
4873 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
4874 if (eOrient
==SVX_ORIENTATION_STACKED
)
4875 eSvxAdjust
= SVX_ADJUST_CENTER
;
4876 // Adjustment fuer bBreak ist hier weggelassen
4877 pSet
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
4879 pEngine
->SetDefaults( pSet
);
4880 pOldPattern
= pPattern
;
4881 pOldCondSet
= pCondSet
;
4883 sal_uLong nControl
= pEngine
->GetControlWord();
4884 if (eOrient
==SVX_ORIENTATION_STACKED
)
4885 nControl
|= EE_CNTRL_ONECHARPERLINE
;
4887 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
4888 pEngine
->SetControlWord( nControl
);
4890 if ( !bHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
4892 // set hyphenator the first time it is needed
4893 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
4894 pEngine
->SetHyphenator( xXHyphenator
);
4895 bHyphenatorSet
= sal_True
;
4898 Color aBackCol
= ((const SvxBrushItem
&)
4899 pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
)).GetColor();
4900 if ( mbUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
4901 aBackCol
.SetColor( nConfBackColor
);
4902 pEngine
->SetBackgroundColor( aBackCol
);
4907 //! Position und Papersize auf EditUtil umstellen !!!
4909 const SvxMarginItem
* pMargin
= (const SvxMarginItem
*)
4910 &pPattern
->GetItem(ATTR_MARGIN
, pCondSet
);
4911 sal_uInt16 nIndent
= 0;
4912 if ( eHorJust
== SVX_HOR_JUSTIFY_LEFT
)
4913 nIndent
= ((const SfxUInt16Item
&)pPattern
->
4914 GetItem(ATTR_INDENT
, pCondSet
)).GetValue();
4916 long nTotalHeight
= nOutHeight
; // ohne Rand abzuziehen
4917 if ( bPixelToLogic
)
4918 nTotalHeight
= mpRefDevice
->PixelToLogic(Size(0,nTotalHeight
)).Height();
4920 long nLeftM
= (long) ( (pMargin
->GetLeftMargin() + nIndent
) * mnPPTX
);
4921 long nTopM
= (long) ( pMargin
->GetTopMargin() * mnPPTY
);
4922 long nRightM
= (long) ( pMargin
->GetRightMargin() * mnPPTX
);
4923 long nBottomM
= (long) ( pMargin
->GetBottomMargin() * mnPPTY
);
4926 nOutWidth
-= nLeftM
+ nRightM
;
4927 nOutHeight
-= nTopM
+ nBottomM
;
4929 // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
4930 long nAttrRotate
= 0;
4933 SvxRotateMode eRotMode
= SVX_ROTATE_MODE_STANDARD
;
4934 if ( eOrient
== SVX_ORIENTATION_STANDARD
)
4936 nAttrRotate
= ((const SfxInt32Item
&)pPattern
->
4937 GetItem(ATTR_ROTATE_VALUE
, pCondSet
)).GetValue();
4940 eRotMode
= (SvxRotateMode
)((const SvxRotateModeItem
&)
4941 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
4943 if ( nAttrRotate
== 18000 )
4944 eRotMode
= SVX_ROTATE_MODE_STANDARD
; // keinen Ueberlauf
4947 nAttrRotate
= -nAttrRotate
;
4949 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100 Grad
4950 nCos
= cos( nRealOrient
);
4951 nSin
= sin( nRealOrient
);
4955 Size aPaperSize
= Size( 1000000, 1000000 );
4956 if (eOrient
==SVX_ORIENTATION_STACKED
)
4957 aPaperSize
.Width() = nOutWidth
; // zum Zentrieren
4962 //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
4963 //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
4964 //! werden koennen -> darum unbegrenzt, also kein Umbruch.
4965 //! Mit versetzten Zeilen waere das folgende richtig:
4966 aPaperSize
.Width() = (long)(nOutHeight
/ fabs(nSin
));
4968 else if (eOrient
== SVX_ORIENTATION_STANDARD
)
4969 aPaperSize
.Width() = nOutWidth
;
4971 aPaperSize
.Width() = nOutHeight
- 1;
4974 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4976 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
4978 // Daten aus Zelle lesen
4982 if (pCell
->GetCellType() == CELLTYPE_EDIT
)
4984 const EditTextObject
* pData
;
4985 ((ScEditCell
*)pCell
)->GetData(pData
);
4988 pEngine
->SetText(*pData
);
4991 OSL_FAIL("pData == 0");
4996 sal_uLong nFormat
= pPattern
->GetNumberFormat(
4997 mpDoc
->GetFormatTable(), pCondSet
);
4998 rtl::OUString aString
;
5000 ScCellFormat::GetString( pCell
,
5001 nFormat
,aString
, &pColor
,
5002 *mpDoc
->GetFormatTable(),
5007 pEngine
->SetText(aString
);
5008 if ( pColor
&& !mbSyntaxMode
&& !( mbUseStyleColor
&& mbForceAutoColor
) )
5009 lcl_SetEditColor( *pEngine
, *pColor
);
5013 SetEditSyntaxColor( *pEngine
, pCell
);
5014 else if ( mbUseStyleColor
&& mbForceAutoColor
)
5015 lcl_SetEditColor( *pEngine
, COL_AUTO
); //! or have a flag at EditEngine
5019 OSL_FAIL("pCell == NULL");
5022 pEngine
->SetUpdateMode( sal_True
); // after SetText, before CalcTextWidth/GetTextHeight
5024 long nEngineWidth
= (long) pEngine
->CalcTextWidth();
5025 long nEngineHeight
= pEngine
->GetTextHeight();
5027 if (nAttrRotate
&& bBreak
)
5029 double nAbsCos
= fabs( nCos
);
5030 double nAbsSin
= fabs( nSin
);
5032 // adjust witdh of papersize for height of text
5036 // everything is in pixels
5037 long nEnginePixel
= mpRefDevice
->LogicToPixel(
5038 Size(0,nEngineHeight
)).Height();
5039 long nEffHeight
= nOutHeight
- (long)(nEnginePixel
* nAbsCos
) + 2;
5040 long nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
5041 sal_Bool bFits
= ( nNewWidth
>= aPaperSize
.Width() );
5046 if ( nNewWidth
< 4 )
5048 // can't fit -> fall back to using half height
5049 nEffHeight
= nOutHeight
/ 2;
5050 nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
5056 // set paper width and get new text height
5057 aPaperSize
.Width() = nNewWidth
;
5059 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
5061 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
5062 //pEngine->QuickFormatDoc( sal_True );
5063 nEngineWidth
= (long) pEngine
->CalcTextWidth();
5064 nEngineHeight
= pEngine
->GetTextHeight();
5069 long nRealWidth
= nEngineWidth
;
5070 long nRealHeight
= nEngineHeight
;
5072 // wenn gedreht, Groesse anpassen
5075 double nAbsCos
= fabs( nCos
);
5076 double nAbsSin
= fabs( nSin
);
5078 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5079 nEngineWidth
= (long) ( nRealWidth
* nAbsCos
+
5080 nRealHeight
* nAbsSin
);
5082 nEngineWidth
= (long) ( nRealHeight
/ nAbsSin
);
5085 nEngineHeight
= (long) ( nRealHeight
* nAbsCos
+
5086 nRealWidth
* nAbsSin
);
5089 if (!nAttrRotate
) // hier nur gedrehter Text
5090 bHidden
= sal_True
; //! vorher abfragen !!!
5092 //! weglassen, was nicht hereinragt
5096 sal_Bool bClip
= false;
5097 Size aClipSize
= Size( nScrX
+nScrW
-nStartX
, nScrY
+nScrH
-nStartY
);
5103 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
5105 aCellSize
= Size( nOutWidth
, nOutHeight
); // Scale ist 1
5107 long nGridWidth
= nEngineWidth
;
5108 sal_Bool bNegative
= false;
5109 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5111 nGridWidth
= aCellSize
.Width() +
5112 Abs((long) ( aCellSize
.Height() * nCos
/ nSin
));
5113 bNegative
= ( pInfo
->nRotateDir
== SC_ROTDIR_LEFT
);
5115 bNegative
= !bNegative
;
5118 // use GetOutputArea to hide the grid
5119 // (clip region is done manually below)
5120 OutputAreaParam aAreaParam
;
5124 SvxCellHorJustify eOutHorJust
= eHorJust
;
5125 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5126 eOutHorJust
= bNegative
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
5127 long nNeededWidth
= nGridWidth
; // in pixel for GetOutputArea
5128 if ( bPixelToLogic
)
5129 nNeededWidth
= mpRefDevice
->LogicToPixel(Size(nNeededWidth
,0)).Width();
5131 GetOutputArea( nX
, nArrY
, nCellStartX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
5132 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
5133 false, false, sal_True
, aAreaParam
);
5137 long nPixelWidth
= bPixelToLogic
?
5138 mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width() : nEngineWidth
;
5139 long nNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
5141 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= sal_True
;
5144 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5145 false, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5146 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5148 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5150 // do width only if rotating within the cell (standard mode)
5151 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5152 sal_True
, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5153 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5156 // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
5157 // (but width is only valid for standard mode)
5158 nRealWidth
= (long) pEngine
->CalcTextWidth();
5159 nRealHeight
= pEngine
->GetTextHeight();
5161 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5162 nEngineWidth
= (long) ( nRealHeight
/ fabs( nSin
) );
5165 long nClipStartX
= nStartX
;
5168 //! Clipping unnoetig, wenn links am Fenster
5170 bClip
= sal_True
; // nur Rest ausgeben!
5173 long nDif
= nScrX
- nStartX
;
5174 nClipStartX
= nScrX
;
5175 aClipSize
.Width() -= nDif
;
5179 long nClipStartY
= nStartY
;
5180 if (nArrY
==0 || bVisChanged
)
5182 if ( nClipStartY
< nRowPosY
)
5184 long nDif
= nRowPosY
- nClipStartY
;
5186 nClipStartY
= nRowPosY
;
5187 aClipSize
.Height() -= nDif
;
5191 bClip
= sal_True
; // always clip at the window/page border
5193 //Rectangle aClipRect;
5196 if ( nAttrRotate
/* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
5198 // gedrehten, ausgerichteten Text nur an den
5199 // Seitengrenzen clippen
5200 nClipStartX
= nScrX
;
5201 aClipSize
.Width() = nScrW
;
5205 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( Rectangle(
5206 Point(nClipStartX
,nClipStartY
), aClipSize
) );
5208 aAreaParam
.maClipRect
= Rectangle(Point(nClipStartX
, nClipStartY
),
5209 aClipSize
); // Scale = 1
5214 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
5217 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
5222 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
5224 aLogicStart
= Point(nStartX
, nStartY
);
5225 if ( eOrient
!=SVX_ORIENTATION_STANDARD
|| !bBreak
)
5227 long nAvailWidth
= aCellSize
.Width();
5228 if (eType
==OUTTYPE_WINDOW
&&
5229 eOrient
!=SVX_ORIENTATION_STACKED
&&
5230 pInfo
&& pInfo
->bAutoFilter
)
5232 // filter drop-down width is now independent from row height
5234 nAvailWidth
-= mpRefDevice
->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE
)).Height();
5236 nAvailWidth
-= DROPDOWN_BITMAP_SIZE
;
5237 long nComp
= nEngineWidth
;
5238 if (nAvailWidth
<nComp
) nAvailWidth
=nComp
;
5241 // horizontale Ausrichtung
5243 if (eOrient
==SVX_ORIENTATION_STANDARD
&& !nAttrRotate
)
5245 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
||
5246 eHorJust
==SVX_HOR_JUSTIFY_CENTER
)
5248 pEngine
->SetUpdateMode( false );
5250 SvxAdjust eSvxAdjust
=
5251 (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
) ?
5252 SVX_ADJUST_RIGHT
: SVX_ADJUST_CENTER
;
5253 pEngine
->SetDefaultItem(
5254 SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
5256 aPaperSize
.Width() = nOutWidth
;
5258 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
5260 pEngine
->SetPaperSize(aPaperSize
);
5262 pEngine
->SetUpdateMode( sal_True
);
5267 // bei gedrehtem Text ist Standard zentriert
5268 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
)
5269 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
5270 else if (eHorJust
==SVX_HOR_JUSTIFY_CENTER
||
5271 eHorJust
==SVX_HOR_JUSTIFY_STANDARD
)
5272 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
5279 aLogicStart
.X() -= mpRefDevice
->PixelToLogic(
5280 Size( nCellWidth
, 0 ) ).Width();
5282 aLogicStart
.X() -= nCellWidth
;
5285 if ( eOrient
==SVX_ORIENTATION_STANDARD
||
5286 eOrient
==SVX_ORIENTATION_STACKED
|| !bBreak
)
5288 if (eVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
5289 eVerJust
==SVX_VER_JUSTIFY_STANDARD
)
5292 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,
5293 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5294 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
5297 aLogicStart
.Y() += aCellSize
.Height() - nEngineHeight
;
5300 else if (eVerJust
==SVX_VER_JUSTIFY_CENTER
)
5303 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,(
5304 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5305 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height())
5308 aLogicStart
.Y() += (aCellSize
.Height() - nEngineHeight
) / 2;
5312 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
5313 OSL_ENSURE( eOrient
== SVX_ORIENTATION_STANDARD
&& nAttrRotate
,
5314 "DrawRotated: no rotation" );
5319 // Attribut ist 1/100, Font 1/10 Grad
5320 nOriVal
= nAttrRotate
/ 10;
5324 if ( nCos
> 0.0 && eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5327 double nH
= nRealHeight
* nCos
;
5328 nAddX
+= nH
* ( nCos
/ fabs(nSin
) );
5330 if ( nCos
< 0.0 && eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5331 nAddX
-= nRealWidth
* nCos
;
5333 nAddX
-= nRealHeight
* nSin
;
5335 nAddY
+= nRealWidth
* nSin
;
5337 nAddY
-= nRealHeight
* nCos
;
5339 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5342 double nSkew
= nTotalHeight
* nCos
/ fabs(nSin
);
5343 if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
5344 nAddX
-= nSkew
* 0.5;
5345 if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nSin
> 0.0 ) ||
5346 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nSin
< 0.0 ) )
5350 if ( eVerJust
== SVX_VER_JUSTIFY_CENTER
)
5351 nUp
= ( aCellSize
.Height() - nEngineHeight
) / 2;
5352 else if ( eVerJust
== SVX_VER_JUSTIFY_TOP
)
5355 nUp
= aCellSize
.Height() - nEngineHeight
;
5357 else // BOTTOM / STANDARD
5360 nUp
= aCellSize
.Height() - nEngineHeight
;
5363 nAddX
+= ( nUp
* nCos
/ fabs(nSin
) );
5366 aLogicStart
.X() += (long) nAddX
;
5367 aLogicStart
.Y() += (long) nAddY
;
5370 // bSimClip is not used here (because nOriVal is set)
5372 if ( pEngine
->IsRightToLeft( 0 ) )
5374 // For right-to-left, EditEngine always calculates its lines
5375 // beginning from the right edge, but EditLine::nStartPosX is
5376 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
5377 Size aLogicPaper
= pEngine
->GetPaperSize();
5378 if ( aLogicPaper
.Width() > USHRT_MAX
)
5380 aLogicPaper
.Width() = USHRT_MAX
;
5381 pEngine
->SetPaperSize(aLogicPaper
);
5385 pEngine
->Draw( mpDev
, aLogicStart
, (short)nOriVal
);
5392 mpDev
->SetClipRegion();
5398 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
5401 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
5409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */