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/adjustitem.hxx>
24 #include <svx/algitem.hxx>
25 #include <editeng/brushitem.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 <editeng/fontitem.hxx>
40 #include <svl/zforlist.hxx>
41 #include <svl/zformat.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/metric.hxx>
44 #include <vcl/outdev.hxx>
45 #include <vcl/pdfextoutdevdata.hxx>
48 #include "document.hxx"
49 #include "formulacell.hxx"
51 #include "patattr.hxx"
52 #include "cellform.hxx"
53 #include "editutil.hxx"
54 #include "progress.hxx"
56 #include "fillinfo.hxx"
57 #include "viewdata.hxx"
58 #include "tabvwsh.hxx"
60 #include "markdata.hxx"
61 #include "stlsheet.hxx"
62 #include "spellcheckcontext.hxx"
64 #include <com/sun/star/i18n/DirectionProperty.hpp>
65 #include <comphelper/string.hxx>
67 #include <boost/ptr_container/ptr_vector.hpp>
71 using namespace com::sun::star
;
73 //! Autofilter-Breite mit column.cxx zusammenfassen
74 #define DROPDOWN_BITMAP_SIZE 18
76 #define DRAWTEXT_MAX 32767
78 const sal_uInt16 SC_SHRINKAGAIN_MAX
= 7;
80 // STATIC DATA -----------------------------------------------------------
83 // -----------------------------------------------------------------------
85 class ScDrawStringsVars
87 ScOutputData
* pOutput
; // Verbindung
89 const ScPatternAttr
* pPattern
; // Attribute
90 const SfxItemSet
* pCondSet
; // aus bedingter Formatierung
92 Font aFont
; // aus Attributen erzeugt
94 long nAscentPixel
; // always pixels
95 SvxCellOrientation eAttrOrient
;
96 SvxCellHorJustify eAttrHorJust
;
97 SvxCellVerJustify eAttrVerJust
;
98 SvxCellJustifyMethod eAttrHorJustMethod
;
99 SvxCellJustifyMethod eAttrVerJustMethod
;
100 const SvxMarginItem
* pMargin
;
104 OUString aString
; // contents
112 ScRefCellValue maLastCell
;
113 sal_uLong nValueFormat
;
118 sal_Bool bPixelToLogic
;
119 sal_Bool bCellContrast
;
121 Color aBackConfigColor
; // used for ScPatternAttr::GetFont calls
122 Color aTextConfigColor
;
127 ScDrawStringsVars(ScOutputData
* pData
, sal_Bool bPTL
);
128 ~ScDrawStringsVars();
130 // SetPattern = ex-SetVars
131 // SetPatternSimple: ohne Font
134 const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
, const ScRefCellValue
& rCell
,
137 void SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
);
139 bool SetText( ScRefCellValue
& rCell
); // TRUE -> pOldPattern vergessen
141 void SetTextToWidthOrHash( ScRefCellValue
& rCell
, long nWidth
);
142 void SetAutoText( const OUString
& rAutoText
);
144 const ScPatternAttr
* GetPattern() const { return pPattern
; }
145 SvxCellOrientation
GetOrient() const { return eAttrOrient
; }
146 SvxCellHorJustify
GetHorJust() const { return eAttrHorJust
; }
147 SvxCellVerJustify
GetVerJust() const { return eAttrVerJust
; }
148 SvxCellJustifyMethod
GetHorJustMethod() const { return eAttrHorJustMethod
; }
149 SvxCellJustifyMethod
GetVerJustMethod() const { return eAttrVerJustMethod
; }
150 const SvxMarginItem
* GetMargin() const { return pMargin
; }
152 sal_uInt16
GetLeftTotal() const { return pMargin
->GetLeftMargin() + nIndent
; }
153 sal_uInt16
GetRightTotal() const { return pMargin
->GetRightMargin() + nIndent
; }
155 const OUString
& GetString() const { return aString
; }
156 const Size
& GetTextSize() const { return aTextSize
; }
157 long GetOriginalWidth() const { return nOriginalWidth
; }
159 sal_uLong
GetResultValueFormat() const;
161 sal_uLong
GetValueFormat() const { return nValueFormat
; }
162 sal_Bool
GetLineBreak() const { return bLineBreak
; }
163 sal_Bool
IsRepeat() const { return bRepeat
; }
164 sal_Bool
IsShrink() const { return bShrink
; }
165 void RepeatToFill( long colWidth
);
167 long GetAscent() const { return nAscentPixel
; }
168 sal_Bool
IsRotated() const { return bRotated
; }
170 void SetShrinkScale( long nScale
, sal_uInt8 nScript
);
172 sal_Bool
HasCondHeight() const { return pCondSet
&& SFX_ITEM_SET
==
173 pCondSet
->GetItemState( ATTR_FONT_HEIGHT
, sal_True
); }
175 sal_Bool
HasEditCharacters() const;
178 long GetMaxDigitWidth(); // in logic units
185 //==================================================================
187 ScDrawStringsVars::ScDrawStringsVars(ScOutputData
* pData
, sal_Bool bPTL
) :
192 eAttrOrient ( SVX_ORIENTATION_STANDARD
),
193 eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD
),
194 eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM
),
195 eAttrHorJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
196 eAttrVerJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
206 bLineBreak ( false ),
209 bPixelToLogic( bPTL
),
213 ScModule
* pScMod
= SC_MOD();
214 bCellContrast
= pOutput
->mbUseStyleColor
&&
215 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
217 const svtools::ColorConfig
& rColorConfig
= pScMod
->GetColorConfig();
218 aBackConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
);
219 aTextConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
);
222 ScDrawStringsVars::~ScDrawStringsVars()
226 void ScDrawStringsVars::SetShrinkScale( long nScale
, sal_uInt8 nScript
)
228 // text remains valid, size is updated
230 OutputDevice
* pDev
= pOutput
->mpDev
;
231 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
232 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
234 // call GetFont with a modified fraction, use only the height
236 Fraction
aFraction( nScale
, 100 );
237 if ( !bPixelToLogic
)
238 aFraction
*= pOutput
->aZoomY
;
240 pPattern
->GetFont( aTmpFont
, SC_AUTOCOL_RAW
, pFmtDevice
, &aFraction
, pCondSet
, nScript
);
241 long nNewHeight
= aTmpFont
.GetHeight();
242 if ( nNewHeight
> 0 )
243 aFont
.SetHeight( nNewHeight
);
245 // set font and dependent variables as in SetPattern
247 pDev
->SetFont( aFont
);
248 if ( pFmtDevice
!= pDev
)
249 pFmtDevice
->SetFont( aFont
);
251 aMetric
= pFmtDevice
->GetFontMetric();
252 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
254 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
255 MapMode aOld
= pDefaultDev
->GetMapMode();
256 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
257 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
258 pDefaultDev
->SetMapMode( aOld
);
261 nAscentPixel
= aMetric
.GetAscent();
263 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
265 SetAutoText( aString
); // same text again, to get text size
270 template<typename _ItemType
, typename _EnumType
>
271 _EnumType
lcl_GetValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
273 const _ItemType
& rItem
= static_cast<const _ItemType
&>(rPattern
.GetItem(nWhich
, pCondSet
));
274 return static_cast<_EnumType
>(rItem
.GetValue());
277 bool lcl_GetBoolValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
279 return lcl_GetValue
<SfxBoolItem
, bool>(rPattern
, nWhich
, pCondSet
);
284 void ScDrawStringsVars::SetPattern(
285 const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
, const ScRefCellValue
& rCell
,
296 // pPattern auswerten
298 OutputDevice
* pDev
= pOutput
->mpDev
;
299 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
300 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
304 ScAutoFontColorMode eColorMode
;
305 if ( pOutput
->mbUseStyleColor
)
307 if ( pOutput
->mbForceAutoColor
)
308 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREALL
: SC_AUTOCOL_IGNOREFONT
;
310 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREBACK
: SC_AUTOCOL_DISPLAY
;
313 eColorMode
= SC_AUTOCOL_PRINT
;
316 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, NULL
, pCondSet
, nScript
,
317 &aBackConfigColor
, &aTextConfigColor
);
319 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, &pOutput
->aZoomY
, pCondSet
, nScript
,
320 &aBackConfigColor
, &aTextConfigColor
);
321 aFont
.SetAlign(ALIGN_BASELINE
);
325 eAttrOrient
= pPattern
->GetCellOrientation( pCondSet
);
329 eAttrHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
331 eAttrVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)pPattern
->GetItem( ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
332 if ( eAttrVerJust
== SVX_VER_JUSTIFY_STANDARD
)
333 eAttrVerJust
= SVX_VER_JUSTIFY_BOTTOM
;
335 // justification method
337 eAttrHorJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
);
338 eAttrVerJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
);
342 bLineBreak
= ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
, pCondSet
)).GetValue();
344 // handle "repeat" alignment
346 bRepeat
= ( eAttrHorJust
== SVX_HOR_JUSTIFY_REPEAT
);
349 // "repeat" disables rotation (before constructing the font)
350 eAttrOrient
= SVX_ORIENTATION_STANDARD
;
352 // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
354 eAttrHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
360 case SVX_ORIENTATION_STANDARD
:
362 bRotated
= (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
, pCondSet
)).GetValue() != 0) &&
365 case SVX_ORIENTATION_STACKED
:
369 case SVX_ORIENTATION_TOPBOTTOM
:
373 case SVX_ORIENTATION_BOTTOMTOP
:
378 OSL_FAIL("Falscher SvxCellOrientation Wert");
383 aFont
.SetOrientation( nRot
);
387 if (pOutput
->mbSyntaxMode
)
388 pOutput
->SetSyntaxColor(&aFont
, rCell
);
390 pDev
->SetFont( aFont
);
391 if ( pFmtDevice
!= pDev
)
392 pFmtDevice
->SetFont( aFont
);
394 aMetric
= pFmtDevice
->GetFontMetric();
397 // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
398 // -> Metric vom Bildschirm nehmen (wie EditEngine!)
401 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
403 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
404 MapMode aOld
= pDefaultDev
->GetMapMode();
405 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
406 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
407 pDefaultDev
->SetMapMode( aOld
);
410 nAscentPixel
= aMetric
.GetAscent();
412 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
414 Color
aULineColor( ((const SvxUnderlineItem
&)pPattern
->GetItem( ATTR_FONT_UNDERLINE
, pCondSet
)).GetColor() );
415 pDev
->SetTextLineColor( aULineColor
);
417 Color
aOLineColor( ((const SvxOverlineItem
&)pPattern
->GetItem( ATTR_FONT_OVERLINE
, pCondSet
)).GetColor() );
418 pDev
->SetOverlineColor( aOLineColor
);
422 nValueFormat
= pPattern
->GetNumberFormat( pOutput
->mpDoc
->GetFormatTable(), pCondSet
);
426 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
427 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
|| eAttrHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
428 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
434 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
436 // zumindest die Text-Groesse muss neu geholt werden
437 //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
442 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
)
448 // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
451 pCondSet
= pSet
; //! noetig ???
455 sal_uLong nOld
= nValueFormat
;
456 const SfxPoolItem
* pFormItem
;
457 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_VALUE_FORMAT
,sal_True
,&pFormItem
) != SFX_ITEM_SET
)
458 pFormItem
= &pPattern
->GetItem(ATTR_VALUE_FORMAT
);
459 const SfxPoolItem
* pLangItem
;
460 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_LANGUAGE_FORMAT
,sal_True
,&pLangItem
) != SFX_ITEM_SET
)
461 pLangItem
= &pPattern
->GetItem(ATTR_LANGUAGE_FORMAT
);
462 nValueFormat
= pOutput
->mpDoc
->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
463 ((SfxUInt32Item
*)pFormItem
)->GetValue(),
464 ((SvxLanguageItem
*)pLangItem
)->GetLanguage() );
466 if (nValueFormat
!= nOld
)
467 maLastCell
.clear(); // immer neu formatieren
471 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
473 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
)
474 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
480 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
483 inline bool SameValue( const ScRefCellValue
& rCell
, const ScRefCellValue
& rOldCell
)
485 return rOldCell
.meType
== CELLTYPE_VALUE
&& rCell
.meType
== CELLTYPE_VALUE
&&
486 rCell
.mfValue
== rOldCell
.mfValue
;
489 bool ScDrawStringsVars::SetText( ScRefCellValue
& rCell
)
491 bool bChanged
= false;
493 if (!rCell
.isEmpty())
495 if (!SameValue(rCell
, maLastCell
))
497 maLastCell
= rCell
; // Zelle merken
500 sal_uLong nFormat
= GetValueFormat();
501 ScCellFormat::GetString( rCell
,
502 nFormat
, aString
, &pColor
,
503 *pOutput
->mpDoc
->GetFormatTable(),
505 pOutput
->mbShowNullValues
,
506 pOutput
->mbShowFormulas
,
510 nPos
= aString
.indexOf( 0x1B );
513 nChar
= aString
[ nPos
+ 1 ];
514 // delete placeholder and char to repeat
515 aString
= aString
.replaceAt( nPos
, 2, "" );
523 if (aString
.getLength() > DRAWTEXT_MAX
)
524 aString
= aString
.copy(0, DRAWTEXT_MAX
);
526 if ( pColor
&& !pOutput
->mbSyntaxMode
&& !( pOutput
->mbUseStyleColor
&& pOutput
->mbForceAutoColor
) )
528 OutputDevice
* pDev
= pOutput
->mpDev
;
529 aFont
.SetColor(*pColor
);
530 pDev
->SetFont( aFont
); // nur fuer Ausgabe
532 maLastCell
.clear(); // naechstes Mal wieder hierherkommen
537 // sonst String/Groesse behalten
541 aString
= OUString();
543 aTextSize
= Size(0,0);
550 void ScDrawStringsVars::SetHashText()
552 SetAutoText(OUString("###"));
555 void ScDrawStringsVars::RepeatToFill( long colWidth
)
557 if ( nPos
== -1 || nPos
> aString
.getLength() )
560 long charWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString(nChar
));
561 if ( charWidth
< 1) return;
563 colWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(colWidth
,0)).Width();
564 // Are there restrictions on the cell type we should filter out here ?
565 long aSpaceToFill
= ( colWidth
- aTextSize
.Width() );
567 if ( aSpaceToFill
<= charWidth
)
570 long nCharsToInsert
= aSpaceToFill
/ charWidth
;
571 OUStringBuffer aFill
;
572 comphelper::string::padToLength(aFill
, nCharsToInsert
, nChar
);
573 aString
= aString
.replaceAt( nPos
, 0, aFill
.makeStringAndClear() );
577 void ScDrawStringsVars::SetTextToWidthOrHash( ScRefCellValue
& rCell
, long nWidth
)
579 // #i113045# do the single-character width calculations in logic units
581 nWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(nWidth
,0)).Width();
583 CellType eType
= rCell
.meType
;
584 if (eType
!= CELLTYPE_VALUE
&& eType
!= CELLTYPE_FORMULA
)
585 // must be a value or formula cell.
588 if (eType
== CELLTYPE_FORMULA
)
590 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
591 if (pFCell
->GetErrCode() != 0 || pOutput
->mbShowFormulas
)
593 SetHashText(); // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
596 // If it's formula, the result must be a value.
597 if (!pFCell
->IsValue())
601 sal_uLong nFormat
= GetResultValueFormat();
602 if ((nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) != 0)
604 // Not 'General' number format. Set hash text and bail out.
609 double fVal
= rCell
.getValue();
611 const SvNumberformat
* pNumFormat
= pOutput
->mpDoc
->GetFormatTable()->GetEntry(nFormat
);
615 long nMaxDigit
= GetMaxDigitWidth();
616 sal_uInt16 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
618 OUString
sTempOut(aString
);
619 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
622 // Failed to get output string. Bail out.
627 sal_uInt8 nSignCount
= 0, nDecimalCount
= 0, nExpCount
= 0;
628 sal_Int32 nLen
= aString
.getLength();
629 sal_Unicode cDecSep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
[0];
630 for( sal_Int32 i
= 0; i
< nLen
; ++i
)
632 sal_Unicode c
= aString
[i
];
635 else if (c
== cDecSep
)
641 // #i112250# A small value might be formatted as "0" when only counting the digits,
642 // but fit into the column when considering the smaller width of the decimal separator.
643 if (aString
== "0" && fVal
!= 0.0)
647 nWidth
+= (nMaxDigit
- GetDotWidth()) * nDecimalCount
;
649 nWidth
+= (nMaxDigit
- GetSignWidth()) * nSignCount
;
651 nWidth
+= (nMaxDigit
- GetExpWidth()) * nExpCount
;
653 if (nDecimalCount
|| nSignCount
|| nExpCount
)
656 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
657 OUString
sTempOut(aString
);
658 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
661 // Failed to get output string. Bail out.
667 long nActualTextWidth
= pOutput
->pFmtDevice
->GetTextWidth(aString
);
668 if (nActualTextWidth
> nWidth
)
670 // Even after the decimal adjustment the text doesn't fit. Give up.
676 maLastCell
.clear(); // #i113022# equal cell and format in another column may give different string
679 void ScDrawStringsVars::SetAutoText( const OUString
& rAutoText
)
683 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
684 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
685 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
686 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
688 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
690 double fMul
= pOutput
->GetStretch();
691 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
694 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
695 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
697 long nTemp
= aTextSize
.Height();
698 aTextSize
.Height() = aTextSize
.Width();
699 aTextSize
.Width() = nTemp
;
702 nOriginalWidth
= aTextSize
.Width();
704 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
706 maLastCell
.clear(); // derselbe Text kann in der naechsten Zelle wieder passen
709 long ScDrawStringsVars::GetMaxDigitWidth()
711 if (nMaxDigitWidth
> 0)
712 return nMaxDigitWidth
;
714 sal_Char cZero
= '0';
715 for (sal_Char i
= 0; i
< 10; ++i
)
717 sal_Char cDigit
= cZero
+ i
;
718 long n
= pOutput
->pFmtDevice
->GetTextWidth(OUString(cDigit
));
719 nMaxDigitWidth
= ::std::max(nMaxDigitWidth
, n
);
721 return nMaxDigitWidth
;
724 long ScDrawStringsVars::GetSignWidth()
729 nSignWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString('-'));
733 long ScDrawStringsVars::GetDotWidth()
738 const OUString
& sep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
;
739 nDotWidth
= pOutput
->pFmtDevice
->GetTextWidth(sep
);
743 long ScDrawStringsVars::GetExpWidth()
748 nExpWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString('E'));
752 void ScDrawStringsVars::TextChanged()
754 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
755 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
756 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
757 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
759 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
761 double fMul
= pOutput
->GetStretch();
762 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
765 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
766 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
768 long nTemp
= aTextSize
.Height();
769 aTextSize
.Height() = aTextSize
.Width();
770 aTextSize
.Width() = nTemp
;
773 nOriginalWidth
= aTextSize
.Width();
775 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
778 sal_Bool
ScDrawStringsVars::HasEditCharacters() const
780 for (sal_Int32 nIdx
= 0; nIdx
< aString
.getLength(); ++nIdx
)
782 switch(aString
[nIdx
])
800 sal_uLong
ScDrawStringsVars::GetResultValueFormat() const
802 // Get the effective number format, including formula result types.
803 // This assumes that a formula cell has already been calculated.
808 //==================================================================
810 double ScOutputData::GetStretch()
812 if ( mpRefDevice
->IsMapMode() )
814 // If a non-trivial MapMode is set, its scale is now already
815 // taken into account in the OutputDevice's font handling
816 // (OutputDevice::ImplNewFont, see #95414#).
817 // The old handling below is only needed for pixel output.
821 // calculation in double is faster than Fraction multiplication
822 // and doesn't overflow
824 if ( mpRefDevice
== pFmtDevice
)
826 MapMode aOld
= mpRefDevice
->GetMapMode();
827 return ((double)aOld
.GetScaleY()) / ((double)aOld
.GetScaleX()) * ((double)aZoomY
) / ((double)aZoomX
);
831 // when formatting for printer, device map mode has already been taken care of
832 return ((double)aZoomY
) / ((double)aZoomX
);
836 //==================================================================
842 static void lcl_DoHyperlinkResult( OutputDevice
* pDev
, const Rectangle
& rRect
, ScRefCellValue
& rCell
)
844 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
848 if (rCell
.meType
== CELLTYPE_FORMULA
)
850 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
851 if ( pFCell
->IsHyperLinkCell() )
852 pFCell
->GetURLResult( aURL
, aCellText
);
855 if ( !aURL
.isEmpty() && pPDFData
)
857 vcl::PDFExtOutDevBookmarkEntry aBookmark
;
858 aBookmark
.nLinkId
= pPDFData
->CreateLink( rRect
);
859 aBookmark
.aBookmark
= aURL
;
860 std::vector
< vcl::PDFExtOutDevBookmarkEntry
>& rBookmarks
= pPDFData
->GetBookmarks();
861 rBookmarks
.push_back( aBookmark
);
865 void ScOutputData::SetSyntaxColor( Font
* pFont
, const ScRefCellValue
& rCell
)
867 switch (rCell
.meType
)
870 pFont
->SetColor(*pValueColor
);
872 case CELLTYPE_STRING
:
873 pFont
->SetColor(*pTextColor
);
875 case CELLTYPE_FORMULA
:
876 pFont
->SetColor(*pFormulaColor
);
880 // added to avoid warnings
885 static void lcl_SetEditColor( EditEngine
& rEngine
, const Color
& rColor
)
887 ESelection
aSel( 0, 0, rEngine
.GetParagraphCount(), 0 );
888 SfxItemSet
aSet( rEngine
.GetEmptyItemSet() );
889 aSet
.Put( SvxColorItem( rColor
, EE_CHAR_COLOR
) );
890 rEngine
.QuickSetAttribs( aSet
, aSel
);
891 // function is called with update mode set to FALSE
894 void ScOutputData::SetEditSyntaxColor( EditEngine
& rEngine
, ScRefCellValue
& rCell
)
897 switch (rCell
.meType
)
900 aColor
= *pValueColor
;
902 case CELLTYPE_STRING
:
903 aColor
= *pTextColor
;
905 case CELLTYPE_FORMULA
:
906 aColor
= *pFormulaColor
;
910 // added to avoid warnings
913 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_Bool
IsAmbiguousScript( sal_uInt8 nScript
)
1078 return ( nScript
!= SCRIPTTYPE_LATIN
&&
1079 nScript
!= SCRIPTTYPE_ASIAN
&&
1080 nScript
!= SCRIPTTYPE_COMPLEX
);
1083 bool ScOutputData::IsEmptyCellText( RowInfo
* pThisRowInfo
, SCCOL nX
, SCROW nY
)
1085 // pThisRowInfo may be NULL
1088 if ( pThisRowInfo
&& nX
<= nX2
)
1089 bEmpty
= pThisRowInfo
->pCellInfo
[nX
+1].bEmptyCellText
;
1092 ScRefCellValue aCell
;
1093 aCell
.assign(*mpDoc
, ScAddress(nX
, nY
, nTab
));
1094 bEmpty
= aCell
.isEmpty();
1097 if ( !bEmpty
&& ( nX
< nX1
|| nX
> nX2
|| !pThisRowInfo
) )
1099 // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
1100 // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
1102 bool bIsPrint
= ( eType
== OUTTYPE_PRINTER
);
1104 if ( bIsPrint
|| bTabProtected
)
1106 const ScProtectionAttr
* pAttr
= (const ScProtectionAttr
*)
1107 mpDoc
->GetEffItem( nX
, nY
, nTab
, ATTR_PROTECTION
);
1108 if ( bIsPrint
&& pAttr
->GetHidePrint() )
1110 else if ( bTabProtected
)
1112 if ( pAttr
->GetHideCell() )
1114 else if ( mbShowFormulas
&& pAttr
->GetHideFormula() )
1116 if (mpDoc
->GetCellType(ScAddress(nX
, nY
, nTab
)) == CELLTYPE_FORMULA
)
1125 void ScOutputData::GetVisibleCell( SCCOL nCol
, SCROW nRow
, SCTAB nTabP
, ScRefCellValue
& rCell
)
1127 rCell
.assign(*mpDoc
, ScAddress(nCol
, nRow
, nTabP
));
1128 if (!rCell
.isEmpty() && IsEmptyCellText(NULL
, nCol
, nRow
))
1132 bool ScOutputData::IsAvailable( SCCOL nX
, SCROW nY
)
1134 // apply the same logic here as in DrawStrings/DrawEdit:
1135 // Stop at non-empty or merged or overlapped cell,
1136 // where a note is empty as well as a cell that's hidden by protection settings
1138 ScRefCellValue aCell
;
1139 aCell
.assign(*mpDoc
, ScAddress(nX
, nY
, nTab
));
1140 if (!aCell
.isEmpty() && !IsEmptyCellText(NULL
, nX
, nY
))
1143 const ScPatternAttr
* pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1144 if ( ((const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
)).IsMerged() ||
1145 ((const ScMergeFlagAttr
&)pPattern
->GetItem(ATTR_MERGE_FLAG
)).IsOverlapped() )
1153 // nX, nArrY: loop variables from DrawStrings / DrawEdit
1154 // nPosX, nPosY: corresponding positions for nX, nArrY
1155 // nCellX, nCellY: position of the cell that contains the text
1156 // nNeeded: Text width, including margin
1157 // rPattern: cell format at nCellX, nCellY
1158 // nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings
1159 // bCellIsValue: if set, don't extend into empty cells
1160 // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
1161 // bOverwrite: if set, also extend into non-empty cells (for rotated text)
1162 // rParam output: various area parameters.
1164 void ScOutputData::GetOutputArea( SCCOL nX
, SCSIZE nArrY
, long nPosX
, long nPosY
,
1165 SCCOL nCellX
, SCROW nCellY
, long nNeeded
,
1166 const ScPatternAttr
& rPattern
,
1167 sal_uInt16 nHorJustify
, bool bCellIsValue
,
1168 bool bBreak
, bool bOverwrite
,
1169 OutputAreaParam
& rParam
)
1171 // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
1172 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1174 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1176 long nCellPosX
= nPosX
; // find nCellX position, starting at nX/nPosX
1177 SCCOL nCompCol
= nX
;
1178 while ( nCellX
> nCompCol
)
1180 //! extra member function for width?
1181 long nColWidth
= ( nCompCol
<= nX2
) ?
1182 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1183 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1184 nCellPosX
+= nColWidth
* nLayoutSign
;
1187 while ( nCellX
< nCompCol
)
1190 long nColWidth
= ( nCompCol
<= nX2
) ?
1191 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1192 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1193 nCellPosX
-= nColWidth
* nLayoutSign
;
1196 long nCellPosY
= nPosY
; // find nCellY position, starting at nArrY/nPosY
1197 SCSIZE nCompArr
= nArrY
;
1198 SCROW nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1199 while ( nCellY
> nCompRow
)
1201 if ( nCompArr
+ 1 < nArrCount
)
1203 nCellPosY
+= pRowInfo
[nCompArr
].nHeight
;
1205 nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1209 sal_uInt16 nDocHeight
= mpDoc
->GetRowHeight( nCompRow
, nTab
);
1211 nCellPosY
+= (long) ( nDocHeight
* mnPPTY
);
1215 nCellPosY
-= (long) mpDoc
->GetScaledRowHeight( nCellY
, nCompRow
-1, nTab
, mnPPTY
);
1217 const ScMergeAttr
* pMerge
= (const ScMergeAttr
*)&rPattern
.GetItem( ATTR_MERGE
);
1218 sal_Bool bMerged
= pMerge
->IsMerged();
1219 long nMergeCols
= pMerge
->GetColMerge();
1220 if ( nMergeCols
== 0 )
1222 long nMergeRows
= pMerge
->GetRowMerge();
1223 if ( nMergeRows
== 0 )
1226 long nMergeSizeX
= 0;
1227 for ( long i
=0; i
<nMergeCols
; i
++ )
1229 long nColWidth
= ( nCellX
+i
<= nX2
) ?
1230 pRowInfo
[0].pCellInfo
[nCellX
+i
+1].nWidth
:
1231 (long) ( mpDoc
->GetColWidth( sal::static_int_cast
<SCCOL
>(nCellX
+i
), nTab
) * mnPPTX
);
1232 nMergeSizeX
+= nColWidth
;
1234 long nMergeSizeY
= 0;
1236 if ( rThisRowInfo
.nRowNo
== nCellY
)
1238 // take first row's height from row info
1239 nMergeSizeY
+= rThisRowInfo
.nHeight
;
1240 nDirect
= 1; // skip in loop
1242 // following rows always from document
1243 nMergeSizeY
+= (long) mpDoc
->GetScaledRowHeight( nCellY
+nDirect
, nCellY
+nMergeRows
-1, nTab
, mnPPTY
);
1245 --nMergeSizeX
; // leave out the grid horizontally, also for alignment (align between grid lines)
1247 rParam
.mnColWidth
= nMergeSizeX
; // store the actual column width.
1250 // construct the rectangles using logical left/right values (justify is called at the end)
1253 // rAlignRect is the single cell or merged area, used for alignment.
1255 rParam
.maAlignRect
.Left() = nCellPosX
;
1256 rParam
.maAlignRect
.Right() = nCellPosX
+ ( nMergeSizeX
- 1 ) * nLayoutSign
;
1257 rParam
.maAlignRect
.Top() = nCellPosY
;
1258 rParam
.maAlignRect
.Bottom() = nCellPosY
+ nMergeSizeY
- 1;
1260 // rClipRect is all cells that are used for output.
1261 // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1263 rParam
.maClipRect
= rParam
.maAlignRect
;
1264 if ( nNeeded
> nMergeSizeX
)
1266 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)nHorJustify
;
1268 long nMissing
= nNeeded
- nMergeSizeX
;
1269 long nLeftMissing
= 0;
1270 long nRightMissing
= 0;
1273 case SVX_HOR_JUSTIFY_LEFT
:
1274 nRightMissing
= nMissing
;
1276 case SVX_HOR_JUSTIFY_RIGHT
:
1277 nLeftMissing
= nMissing
;
1279 case SVX_HOR_JUSTIFY_CENTER
:
1280 nLeftMissing
= nMissing
/ 2;
1281 nRightMissing
= nMissing
- nLeftMissing
;
1285 // added to avoid warnings
1289 // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1291 ::std::swap( nLeftMissing
, nRightMissing
);
1293 SCCOL nRightX
= nCellX
;
1294 SCCOL nLeftX
= nCellX
;
1295 if ( !bMerged
&& !bCellIsValue
&& !bBreak
)
1297 // look for empty cells into which the text can be extended
1299 while ( nRightMissing
> 0 && nRightX
< MAXCOL
&& ( bOverwrite
|| IsAvailable( nRightX
+1, nCellY
) ) )
1302 long nAdd
= (long) ( mpDoc
->GetColWidth( nRightX
, nTab
) * mnPPTX
);
1303 nRightMissing
-= nAdd
;
1304 rParam
.maClipRect
.Right() += nAdd
* nLayoutSign
;
1306 if ( rThisRowInfo
.nRowNo
== nCellY
&& nRightX
>= nX1
&& nRightX
<= nX2
)
1307 rThisRowInfo
.pCellInfo
[nRightX
].bHideGrid
= sal_True
;
1310 while ( nLeftMissing
> 0 && nLeftX
> 0 && ( bOverwrite
|| IsAvailable( nLeftX
-1, nCellY
) ) )
1312 if ( rThisRowInfo
.nRowNo
== nCellY
&& nLeftX
>= nX1
&& nLeftX
<= nX2
)
1313 rThisRowInfo
.pCellInfo
[nLeftX
].bHideGrid
= sal_True
;
1316 long nAdd
= (long) ( mpDoc
->GetColWidth( nLeftX
, nTab
) * mnPPTX
);
1317 nLeftMissing
-= nAdd
;
1318 rParam
.maClipRect
.Left() -= nAdd
* nLayoutSign
;
1322 // Set flag and reserve space for clipping mark triangle,
1323 // even if rThisRowInfo isn't for nCellY (merged cells).
1324 if ( nRightMissing
> 0 && bMarkClipped
&& nRightX
>= nX1
&& nRightX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1326 rThisRowInfo
.pCellInfo
[nRightX
+1].nClipMark
|= SC_CLIPMARK_RIGHT
;
1327 bAnyClipped
= sal_True
;
1328 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1329 rParam
.maClipRect
.Right() -= nMarkPixel
* nLayoutSign
;
1331 if ( nLeftMissing
> 0 && bMarkClipped
&& nLeftX
>= nX1
&& nLeftX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1333 rThisRowInfo
.pCellInfo
[nLeftX
+1].nClipMark
|= SC_CLIPMARK_LEFT
;
1334 bAnyClipped
= sal_True
;
1335 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1336 rParam
.maClipRect
.Left() += nMarkPixel
* nLayoutSign
;
1339 rParam
.mbLeftClip
= ( nLeftMissing
> 0 );
1340 rParam
.mbRightClip
= ( nRightMissing
> 0 );
1344 rParam
.mbLeftClip
= rParam
.mbRightClip
= false;
1346 // leave space for AutoFilter on screen
1347 // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1349 if ( eType
==OUTTYPE_WINDOW
&&
1350 ( static_cast<const ScMergeFlagAttr
&>(rPattern
.GetItem(ATTR_MERGE_FLAG
)).GetValue() & (SC_MF_AUTO
|SC_MF_BUTTON
|SC_MF_BUTTON_POPUP
) ) &&
1351 ( !bBreak
|| mpRefDevice
== pFmtDevice
) )
1353 // filter drop-down width is now independent from row height
1354 const long nFilter
= DROPDOWN_BITMAP_SIZE
;
1355 sal_Bool bFit
= ( nNeeded
+ nFilter
<= nMergeSizeX
);
1356 if ( bFit
|| bCellIsValue
)
1358 // content fits even in the remaining area without the filter button
1359 // -> align within that remaining area
1361 rParam
.maAlignRect
.Right() -= nFilter
* nLayoutSign
;
1362 rParam
.maClipRect
.Right() -= nFilter
* nLayoutSign
;
1364 // if a number doesn't fit, don't hide part of the number behind the button
1365 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1368 rParam
.mbLeftClip
= rParam
.mbRightClip
= sal_True
;
1373 // justify both rectangles for alignment calculation, use with DrawText etc.
1375 rParam
.maAlignRect
.Justify();
1376 rParam
.maClipRect
.Justify();
1381 bool beginsWithRTLCharacter(const OUString
& rStr
)
1386 switch (ScGlobal::pCharClass
->getCharacterDirection(rStr
, 0))
1388 case i18n::DirectionProperty_RIGHT_TO_LEFT
:
1389 case i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC
:
1390 case i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING
:
1391 case i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
:
1402 /** Get left, right or centered alignment from RTL context.
1404 Does not return standard, block or repeat, for these the contextual left or
1405 right alignment is returned.
1407 static SvxCellHorJustify
getAlignmentFromContext( SvxCellHorJustify eInHorJust
,
1408 bool bCellIsValue
, const OUString
& rText
,
1409 const ScPatternAttr
& rPattern
, const SfxItemSet
* pCondSet
,
1410 const ScDocument
* pDoc
, SCTAB nTab
)
1412 SvxCellHorJustify eHorJustContext
= eInHorJust
;
1413 bool bUseWritingDirection
= false;
1414 if (eInHorJust
== SVX_HOR_JUSTIFY_STANDARD
)
1416 // fdo#32530: Default alignment depends on value vs
1417 // string, and the direction of the 1st letter.
1418 if (beginsWithRTLCharacter( rText
))
1419 eHorJustContext
= bCellIsValue
? SVX_HOR_JUSTIFY_LEFT
: SVX_HOR_JUSTIFY_RIGHT
;
1420 else if (bCellIsValue
)
1421 eHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
1423 bUseWritingDirection
= true;
1426 if (bUseWritingDirection
||
1427 eInHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eInHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
1429 sal_uInt16 nDirection
= lcl_GetValue
<SvxFrameDirectionItem
, sal_uInt16
>( rPattern
, ATTR_WRITINGDIR
, pCondSet
);
1430 if (nDirection
== FRMDIR_HORI_LEFT_TOP
|| nDirection
== FRMDIR_VERT_TOP_LEFT
)
1431 eHorJustContext
= SVX_HOR_JUSTIFY_LEFT
;
1432 else if (nDirection
== FRMDIR_ENVIRONMENT
)
1434 SAL_WARN_IF( !pDoc
, "sc.ui", "getAlignmentFromContext - pDoc==NULL");
1435 eHorJustContext
= (pDoc
&& pDoc
->IsLayoutRTL(nTab
)) ? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
1438 eHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
1440 return eHorJustContext
;
1443 void ScOutputData::DrawStrings( sal_Bool bPixelToLogic
)
1445 OSL_ENSURE( mpDev
== mpRefDevice
||
1446 mpDev
->GetMapMode().GetMapUnit() == mpRefDevice
->GetMapMode().GetMapUnit(),
1447 "DrawStrings: unterschiedliche MapUnits ?!?!" );
1449 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, mpDev
->GetExtOutDevData() );
1451 bool bWasIdleEnabled
= mpDoc
->IsIdleEnabled();
1452 mpDoc
->EnableIdle(false);
1454 ScDrawStringsVars
aVars( this, bPixelToLogic
);
1456 sal_Bool bProgress
= false;
1458 long nInitPosX
= nScrX
;
1460 nInitPosX
+= nMirrorW
- 1; // pixels
1461 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1463 SCCOL nLastContentCol
= MAXCOL
;
1465 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
1466 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
1467 SCCOL nLoopStartX
= nX1
;
1469 --nLoopStartX
; // start before nX1 for rest of long text to the left
1471 // variables for GetOutputArea
1472 OutputAreaParam aAreaParam
;
1473 sal_Bool bCellIsValue
= false;
1474 long nNeededWidth
= 0;
1475 const ScPatternAttr
* pPattern
= NULL
;
1476 const SfxItemSet
* pCondSet
= NULL
;
1477 const ScPatternAttr
* pOldPattern
= NULL
;
1478 const SfxItemSet
* pOldCondSet
= NULL
;
1479 sal_uInt8 nOldScript
= 0;
1481 // alternative pattern instances in case we need to modify the pattern
1482 // before processing the cell value.
1483 ::boost::ptr_vector
<ScPatternAttr
> aAltPatterns
;
1486 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1488 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1489 if ( pThisRowInfo
->bChanged
)
1491 SCROW nY
= pThisRowInfo
->nRowNo
;
1492 long nPosX
= nInitPosX
;
1493 if ( nLoopStartX
< nX1
)
1494 nPosX
-= pRowInfo
[0].pCellInfo
[nLoopStartX
+1].nWidth
* nLayoutSign
;
1495 for (SCCOL nX
=nLoopStartX
; nX
<=nX2
; nX
++)
1497 bool bMergeEmpty
= false;
1498 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
1499 bool bEmpty
= nX
< nX1
|| pInfo
->bEmptyCellText
;
1501 SCCOL nCellX
= nX
; // position where the cell really starts
1503 bool bDoCell
= false;
1504 bool bNeedEdit
= false;
1507 // Part of a merged cell?
1510 bool bOverlapped
= (pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
);
1515 SCCOL nOverX
; // start of the merged cells
1517 sal_Bool bVisChanged
= !pRowInfo
[nArrY
-1].bChanged
;
1518 if (GetMergeOrigin( nX
,nY
, nArrY
, nOverX
,nOverY
, bVisChanged
))
1529 // Rest of a long text further to the left?
1532 if ( bEmpty
&& !bMergeEmpty
&& nX
< nX1
&& !bOverlapped
)
1535 while (nTempX
> 0 && IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1538 if ( nTempX
< nX1
&&
1539 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1540 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX1
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1548 // Rest of a long text further to the right?
1551 if ( bEmpty
&& !bMergeEmpty
&& nX
== nX2
&& !bOverlapped
)
1553 // don't have to look further than nLastContentCol
1556 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1560 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1561 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1569 // normal visible cell
1576 // don't output the cell that's being edited
1579 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
1582 // skip text in cell if data bar/icon set is set and only value selected
1585 if(pInfo
->pDataBar
&& !pInfo
->pDataBar
->mbShowValue
)
1587 if(pInfo
->pIconSet
&& !pInfo
->pIconSet
->mbShowValue
)
1592 // output the cell text
1595 ScRefCellValue aCell
;
1598 if ( nCellY
== nY
&& nCellX
== nX
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1599 aCell
= pThisRowInfo
->pCellInfo
[nCellX
+1].maCell
;
1601 GetVisibleCell( nCellX
, nCellY
, nTab
, aCell
); // get from document
1602 if (aCell
.isEmpty())
1604 else if (aCell
.meType
== CELLTYPE_EDIT
)
1608 // Check if this cell is mis-spelled.
1609 if (bDoCell
&& !bNeedEdit
&& aCell
.meType
== CELLTYPE_STRING
)
1611 if (mpSpellCheckCxt
&& mpSpellCheckCxt
->isMisspelled(nCellX
, nCellY
))
1615 if (bDoCell
&& !bNeedEdit
)
1617 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1619 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
1620 pPattern
= rCellInfo
.pPatternAttr
;
1621 pCondSet
= rCellInfo
.pConditionSet
;
1625 // #i68085# pattern from cell info for hidden columns is null,
1626 // test for null is quicker than using column flags
1627 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1628 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1631 else // get from document
1633 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1634 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1636 if ( mpDoc
->GetPreviewFont() || mpDoc
->GetPreviewCellStyle() )
1638 aAltPatterns
.push_back(new ScPatternAttr(*pPattern
));
1639 ScPatternAttr
* pAltPattern
= &aAltPatterns
.back();
1640 if ( ScStyleSheet
* pPreviewStyle
= mpDoc
->GetPreviewCellStyle( nCellX
, nCellY
, nTab
) )
1642 pAltPattern
->SetStyleSheet(pPreviewStyle
);
1644 else if ( SfxItemSet
* pFontSet
= mpDoc
->GetPreviewFont( nCellX
, nCellY
, nTab
) )
1646 const SfxPoolItem
* pItem
;
1647 if ( pFontSet
->GetItemState( ATTR_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1648 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1649 if ( pFontSet
->GetItemState( ATTR_CJK_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1650 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1651 if ( pFontSet
->GetItemState( ATTR_CTL_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1652 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1654 pPattern
= pAltPattern
;
1657 if (aCell
.hasNumeric() &&
1658 static_cast<const SfxBoolItem
&>(
1659 pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue())
1661 // Disable line break when the cell content is numeric.
1662 aAltPatterns
.push_back(new ScPatternAttr(*pPattern
));
1663 ScPatternAttr
* pAltPattern
= &aAltPatterns
.back();
1664 SfxBoolItem
aLineBreak(ATTR_LINEBREAK
, false);
1665 pAltPattern
->GetItemSet().Put(aLineBreak
);
1666 pPattern
= pAltPattern
;
1669 sal_uInt8 nScript
= mpDoc
->GetCellScriptType(
1670 ScAddress(nCellX
, nCellY
, nTab
),
1671 pPattern
->GetNumberFormat(mpDoc
->GetFormatTable(), pCondSet
));
1674 nScript
= ScGlobal::GetDefaultScriptType();
1676 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
||
1677 nScript
!= nOldScript
|| mbSyntaxMode
)
1679 if ( StringDiffer(pOldPattern
,pPattern
) ||
1680 pCondSet
!= pOldCondSet
|| nScript
!= nOldScript
|| mbSyntaxMode
)
1682 aVars
.SetPattern(pPattern
, pCondSet
, aCell
, nScript
);
1685 aVars
.SetPatternSimple( pPattern
, pCondSet
);
1686 pOldPattern
= pPattern
;
1687 pOldCondSet
= pCondSet
;
1688 nOldScript
= nScript
;
1691 // use edit engine for rotated, stacked or mixed-script text
1692 if ( aVars
.GetOrient() == SVX_ORIENTATION_STACKED
||
1693 aVars
.IsRotated() || IsAmbiguousScript(nScript
) )
1694 bNeedEdit
= sal_True
;
1696 if (bDoCell
&& !bNeedEdit
)
1698 bool bFormulaCell
= (aCell
.meType
== CELLTYPE_FORMULA
);
1700 lcl_CreateInterpretProgress(bProgress
, mpDoc
, aCell
.mpFormula
);
1701 if ( aVars
.SetText(aCell
) )
1703 bNeedEdit
= aVars
.HasEditCharacters() || (bFormulaCell
&& aCell
.mpFormula
->IsMultilineResult());
1705 long nTotalMargin
= 0;
1706 SvxCellHorJustify eOutHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
1707 if (bDoCell
&& !bNeedEdit
)
1709 CellType eCellType
= aCell
.meType
;
1710 bCellIsValue
= ( eCellType
== CELLTYPE_VALUE
);
1711 if ( eCellType
== CELLTYPE_FORMULA
)
1713 ScFormulaCell
* pFCell
= aCell
.mpFormula
;
1714 bCellIsValue
= pFCell
->IsRunning() || pFCell
->IsValue();
1717 eOutHorJust
= getAlignmentFromContext( aVars
.GetHorJust(), bCellIsValue
, aVars
.GetString(),
1718 *pPattern
, pCondSet
, mpDoc
, nTab
);
1720 bool bBreak
= ( aVars
.GetLineBreak() || aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
);
1721 // #i111387# #o11817313# disable automatic line breaks only for "General" number format
1722 if (bBreak
&& bCellIsValue
&& (aVars
.GetResultValueFormat() % SV_COUNTRY_LANGUAGE_OFFSET
) == 0)
1725 bool bRepeat
= aVars
.IsRepeat() && !bBreak
;
1726 bool bShrink
= aVars
.IsShrink() && !bBreak
&& !bRepeat
;
1729 static_cast<long>(aVars
.GetLeftTotal() * mnPPTX
) +
1730 static_cast<long>(aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1732 nNeededWidth
= aVars
.GetTextSize().Width() + nTotalMargin
;
1734 // GetOutputArea gives justfied rectangles
1735 GetOutputArea( nX
, nArrY
, nPosX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
1736 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
1737 bCellIsValue
|| bRepeat
|| bShrink
, bBreak
, false,
1740 aVars
.RepeatToFill( aAreaParam
.mnColWidth
- nTotalMargin
);
1743 if ( aVars
.GetOrient() != SVX_ORIENTATION_STANDARD
)
1745 // Only horizontal scaling is handled here.
1746 // DrawEdit is used to vertically scale 90 deg rotated text.
1747 bNeedEdit
= sal_True
;
1749 else if ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) // horizontal
1751 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1752 long nScaleSize
= aVars
.GetTextSize().Width(); // without margin
1754 if ( nScaleSize
> 0 ) // 0 if the text is empty (formulas, number formats)
1756 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
1758 aVars
.SetShrinkScale( nScale
, nOldScript
);
1759 long nNewSize
= aVars
.GetTextSize().Width();
1761 sal_uInt16 nShrinkAgain
= 0;
1762 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
1764 // If the text is still too large, reduce the scale again by 10%, until it fits,
1765 // at most 7 times (it's less than 50% of the calculated scale then).
1767 nScale
= ( nScale
* 9 ) / 10;
1768 aVars
.SetShrinkScale( nScale
, nOldScript
);
1769 nNewSize
= aVars
.GetTextSize().Width();
1772 // If even at half the size the font still isn't rendered smaller,
1773 // fall back to normal clipping (showing ### for numbers).
1774 if ( nNewSize
<= nAvailable
)
1775 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1782 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
)
1784 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1785 long nRepeatSize
= aVars
.GetTextSize().Width(); // without margin
1786 // When formatting for the printer, the text sizes don't always add up.
1787 // Round down (too few repetitions) rather than exceeding the cell size then:
1788 if ( pFmtDevice
!= mpRefDevice
)
1790 if ( nRepeatSize
> 0 )
1792 long nRepeatCount
= nAvailable
/ nRepeatSize
;
1793 if ( nRepeatCount
> 1 )
1795 OUString aCellStr
= aVars
.GetString();
1796 OUString aRepeated
= aCellStr
;
1797 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
1798 aRepeated
+= aCellStr
;
1799 aVars
.SetAutoText( aRepeated
);
1804 // use edit engine if automatic line breaks are needed
1807 if ( aVars
.GetOrient() == SVX_ORIENTATION_STANDARD
)
1808 bNeedEdit
= ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
);
1811 long nHeight
= aVars
.GetTextSize().Height() +
1812 (long)(aVars
.GetMargin()->GetTopMargin()*mnPPTY
) +
1813 (long)(aVars
.GetMargin()->GetBottomMargin()*mnPPTY
);
1814 bNeedEdit
= ( nHeight
> aAreaParam
.maClipRect
.GetHeight() );
1820 aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
&&
1821 aVars
.GetHorJustMethod() == SVX_JUSTIFY_METHOD_DISTRIBUTE
;
1826 // mark the cell in CellInfo to be drawn in DrawEdit:
1827 // Cells to the left are marked directly, cells to the
1828 // right are handled by the flag for nX2
1829 SCCOL nMarkX
= ( nCellX
<= nX2
) ? nCellX
: nX2
;
1830 RowInfo
* pMarkRowInfo
= ( nCellY
== nY
) ? pThisRowInfo
: &pRowInfo
[0];
1831 pMarkRowInfo
->pCellInfo
[nMarkX
+1].bEditEngine
= sal_True
;
1832 bDoCell
= false; // don't draw here
1836 if ( bCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
1839 aVars
.SetHashText();
1841 // Adjust the decimals to fit the available column width.
1842 aVars
.SetTextToWidthOrHash(aCell
, aAreaParam
.mnColWidth
- nTotalMargin
);
1844 nNeededWidth
= aVars
.GetTextSize().Width() +
1845 (long) ( aVars
.GetLeftTotal() * mnPPTX
) +
1846 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1847 if ( nNeededWidth
<= aAreaParam
.maClipRect
.GetWidth() )
1848 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1850 // If the "###" replacement doesn't fit into the cells, no clip marks
1851 // are shown, as the "###" already denotes too little space.
1852 // The rectangles from the first GetOutputArea call remain valid.
1855 long nJustPosX
= aAreaParam
.maAlignRect
.Left(); // "justified" - effect of alignment will be added
1856 long nJustPosY
= aAreaParam
.maAlignRect
.Top();
1857 long nAvailWidth
= aAreaParam
.maAlignRect
.GetWidth();
1858 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight();
1860 sal_Bool bOutside
= ( aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
1861 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
1863 aAreaParam
.maClipRect
.Left() = nScrX
;
1864 aAreaParam
.mbLeftClip
= sal_True
;
1866 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
1868 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
1869 aAreaParam
.mbRightClip
= sal_True
;
1872 sal_Bool bHClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
1873 sal_Bool bVClip
= false;
1875 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
1877 aAreaParam
.maClipRect
.Top() = nScrY
;
1880 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
1882 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
1887 // horizontalen Platz testen
1890 sal_Bool bRightAdjusted
= false; // to correct text width calculation later
1891 sal_Bool bNeedEditEngine
= false;
1892 if ( !bNeedEditEngine
&& !bOutside
)
1894 switch (eOutHorJust
)
1896 case SVX_HOR_JUSTIFY_LEFT
:
1897 nJustPosX
+= (long) ( aVars
.GetLeftTotal() * mnPPTX
);
1899 case SVX_HOR_JUSTIFY_RIGHT
:
1900 nJustPosX
+= nAvailWidth
- aVars
.GetTextSize().Width() -
1901 (long) ( aVars
.GetRightTotal() * mnPPTX
);
1902 bRightAdjusted
= sal_True
;
1904 case SVX_HOR_JUSTIFY_CENTER
:
1905 nJustPosX
+= ( nAvailWidth
- aVars
.GetTextSize().Width() +
1906 (long) ( aVars
.GetLeftTotal() * mnPPTX
) -
1907 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
) ) / 2;
1911 // added to avoid warnings
1915 long nTestClipHeight
= aVars
.GetTextSize().Height();
1916 switch (aVars
.GetVerJust())
1918 case SVX_VER_JUSTIFY_TOP
:
1919 case SVX_VER_JUSTIFY_BLOCK
:
1921 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1923 nTestClipHeight
+= nTop
;
1926 case SVX_VER_JUSTIFY_BOTTOM
:
1928 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1929 nJustPosY
+= nOutHeight
- aVars
.GetTextSize().Height() - nBot
;
1930 nTestClipHeight
+= nBot
;
1933 case SVX_VER_JUSTIFY_CENTER
:
1935 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1936 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1937 nJustPosY
+= ( nOutHeight
+ nTop
-
1938 aVars
.GetTextSize().Height() - nBot
) / 2;
1939 nTestClipHeight
+= std::abs( nTop
- nBot
);
1944 // added to avoid warnings
1948 if ( nTestClipHeight
> nOutHeight
)
1950 // kein vertikales Clipping beim Drucken von Zellen mit
1951 // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1952 if ( eType
!= OUTTYPE_PRINTER
||
1953 ( mpDoc
->GetRowFlags( nCellY
, nTab
) & CR_MANUALSIZE
) ||
1954 ( aVars
.HasCondHeight() ) )
1958 if ( bHClip
|| bVClip
)
1960 // nur die betroffene Dimension clippen,
1961 // damit bei nicht-proportionalem Resize nicht alle
1962 // rechtsbuendigen Zahlen abgeschnitten werden:
1966 aAreaParam
.maClipRect
.Left() = nScrX
;
1967 aAreaParam
.maClipRect
.Right() = nScrX
+nScrW
;
1971 aAreaParam
.maClipRect
.Top() = nScrY
;
1972 aAreaParam
.maClipRect
.Bottom() = nScrY
+nScrH
;
1975 // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1976 // so it can be modified here
1978 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
1983 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
1986 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
1989 Point
aURLStart( nJustPosX
, nJustPosY
); // copy before modifying for orientation
1991 switch (aVars
.GetOrient())
1993 case SVX_ORIENTATION_STANDARD
:
1994 nJustPosY
+= aVars
.GetAscent();
1996 case SVX_ORIENTATION_TOPBOTTOM
:
1997 nJustPosX
+= aVars
.GetTextSize().Width() - aVars
.GetAscent();
1999 case SVX_ORIENTATION_BOTTOMTOP
:
2000 nJustPosY
+= aVars
.GetTextSize().Height();
2001 nJustPosX
+= aVars
.GetAscent();
2005 // added to avoid warnings
2009 // When clipping, the visible part is now completely defined by the alignment,
2010 // there's no more special handling to show the right part of RTL text.
2012 Point
aDrawTextPos( nJustPosX
, nJustPosY
);
2013 if ( bPixelToLogic
)
2015 // undo text width adjustment in pixels
2017 aDrawTextPos
.X() += aVars
.GetTextSize().Width();
2019 aDrawTextPos
= mpRefDevice
->PixelToLogic( aDrawTextPos
);
2021 // redo text width adjustment in logic units
2023 aDrawTextPos
.X() -= aVars
.GetOriginalWidth();
2026 // in Metafiles immer DrawTextArray, damit die Positionen mit
2027 // aufgezeichnet werden (fuer nicht-proportionales Resize):
2029 OUString aString
= aVars
.GetString();
2030 if (bMetaFile
|| pFmtDevice
!= mpDev
|| aZoomX
!= aZoomY
)
2032 sal_Int32
* pDX
= new sal_Int32
[aString
.getLength()];
2033 pFmtDevice
->GetTextArray( aString
, pDX
);
2035 if ( !mpRefDevice
->GetConnectMetaFile() ||
2036 mpRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
2038 double fMul
= GetStretch();
2039 sal_Int32 nLen
= aString
.getLength();
2040 for( sal_Int32 i
= 0; i
<nLen
; i
++ )
2041 pDX
[i
] = (long)(pDX
[i
] / fMul
+ 0.5);
2044 mpDev
->DrawTextArray( aDrawTextPos
, aString
, pDX
);
2048 mpDev
->DrawText( aDrawTextPos
, aString
);
2050 if ( bHClip
|| bVClip
)
2055 mpDev
->SetClipRegion();
2058 // PDF: whole-cell hyperlink from formula?
2059 bool bHasURL
= pPDFData
&& aCell
.meType
== CELLTYPE_FORMULA
&& aCell
.mpFormula
->IsHyperLinkCell();
2062 Rectangle
aURLRect( aURLStart
, aVars
.GetTextSize() );
2063 lcl_DoHyperlinkResult(mpDev
, aURLRect
, aCell
);
2067 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2070 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2073 ScProgress::DeleteInterpretProgress();
2074 mpDoc
->EnableIdle(bWasIdleEnabled
);
2077 // -------------------------------------------------------------------------------
2079 ScFieldEditEngine
* ScOutputData::CreateOutputEditEngine()
2081 ScFieldEditEngine
* pEngine
= new ScFieldEditEngine(mpDoc
, mpDoc
->GetEnginePool());
2082 pEngine
->SetUpdateMode( false );
2083 // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
2084 pEngine
->SetRefDevice( pFmtDevice
);
2085 sal_uLong nCtrl
= pEngine
->GetControlWord();
2086 if ( bShowSpellErrors
)
2087 nCtrl
|= EE_CNTRL_ONLINESPELLING
;
2088 if ( eType
== OUTTYPE_PRINTER
)
2089 nCtrl
&= ~EE_CNTRL_MARKFIELDS
;
2090 if ( eType
== OUTTYPE_WINDOW
&& mpRefDevice
== pFmtDevice
)
2091 nCtrl
&= ~EE_CNTRL_FORMAT100
; // use the actual MapMode
2092 pEngine
->SetControlWord( nCtrl
);
2093 mpDoc
->ApplyAsianEditSettings( *pEngine
);
2094 pEngine
->EnableAutoColor( mbUseStyleColor
);
2095 pEngine
->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection
)mpDoc
->GetEditTextDirection( nTab
) );
2099 static void lcl_ClearEdit( EditEngine
& rEngine
) // Text und Attribute
2101 rEngine
.SetUpdateMode( false );
2103 rEngine
.SetText(EMPTY_OUSTRING
);
2104 // keine Para-Attribute uebrigbehalten...
2105 const SfxItemSet
& rPara
= rEngine
.GetParaAttribs(0);
2107 rEngine
.SetParaAttribs( 0,
2108 SfxItemSet( *rPara
.GetPool(), rPara
.GetRanges() ) );
2111 static bool lcl_SafeIsValue( ScRefCellValue
& rCell
)
2113 switch (rCell
.meType
)
2115 case CELLTYPE_VALUE
:
2117 case CELLTYPE_FORMULA
:
2119 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
2120 if (pFCell
->IsRunning() || pFCell
->IsValue())
2126 // added to avoid warnings
2132 static void lcl_ScaleFonts( EditEngine
& rEngine
, long nPercent
)
2134 sal_Bool bUpdateMode
= rEngine
.GetUpdateMode();
2136 rEngine
.SetUpdateMode( false );
2138 sal_Int32 nParCount
= rEngine
.GetParagraphCount();
2139 for (sal_Int32 nPar
=0; nPar
<nParCount
; nPar
++)
2141 std::vector
<sal_uInt16
> aPortions
;
2142 rEngine
.GetPortions( nPar
, aPortions
);
2144 sal_uInt16 nStart
= 0;
2145 for ( std::vector
<sal_uInt16
>::const_iterator
it(aPortions
.begin()); it
!= aPortions
.end(); ++it
)
2147 sal_uInt16 nEnd
= *it
;
2148 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
2149 SfxItemSet aAttribs
= rEngine
.GetAttribs( aSel
);
2151 long nWestern
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT
)).GetHeight();
2152 long nCJK
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CJK
)).GetHeight();
2153 long nCTL
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CTL
)).GetHeight();
2155 nWestern
= ( nWestern
* nPercent
) / 100;
2156 nCJK
= ( nCJK
* nPercent
) / 100;
2157 nCTL
= ( nCTL
* nPercent
) / 100;
2159 aAttribs
.Put( SvxFontHeightItem( nWestern
, 100, EE_CHAR_FONTHEIGHT
) );
2160 aAttribs
.Put( SvxFontHeightItem( nCJK
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
2161 aAttribs
.Put( SvxFontHeightItem( nCTL
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
2163 rEngine
.QuickSetAttribs( aAttribs
, aSel
); //! remove paragraph attributes from aAttribs?
2170 rEngine
.SetUpdateMode( sal_True
);
2173 static long lcl_GetEditSize( EditEngine
& rEngine
, sal_Bool bWidth
, sal_Bool bSwap
, long nAttrRotate
)
2180 long nRealWidth
= (long) rEngine
.CalcTextWidth();
2181 long nRealHeight
= rEngine
.GetTextHeight();
2183 // assuming standard mode, otherwise width isn't used
2185 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100th degrees
2186 double nAbsCos
= fabs( cos( nRealOrient
) );
2187 double nAbsSin
= fabs( sin( nRealOrient
) );
2189 return (long) ( nRealWidth
* nAbsCos
+ nRealHeight
* nAbsSin
);
2191 return (long) ( nRealHeight
* nAbsCos
+ nRealWidth
* nAbsSin
);
2194 return (long) rEngine
.CalcTextWidth();
2196 return rEngine
.GetTextHeight();
2200 void ScOutputData::ShrinkEditEngine( EditEngine
& rEngine
, const Rectangle
& rAlignRect
,
2201 long nLeftM
, long nTopM
, long nRightM
, long nBottomM
,
2202 sal_Bool bWidth
, sal_uInt16 nOrient
, long nAttrRotate
, sal_Bool bPixelToLogic
,
2203 long& rEngineWidth
, long& rEngineHeight
, long& rNeededPixel
, bool& rLeftClip
, bool& rRightClip
)
2209 long nScaleSize
= bPixelToLogic
?
2210 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2212 // Don't scale if it fits already.
2213 // Allowing to extend into the margin, to avoid scaling at optimal height.
2214 if ( nScaleSize
<= rAlignRect
.GetHeight() )
2217 sal_Bool bSwap
= ( nOrient
== SVX_ORIENTATION_TOPBOTTOM
|| nOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2218 long nAvailable
= rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2219 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2221 lcl_ScaleFonts( rEngine
, nScale
);
2222 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2223 long nNewSize
= bPixelToLogic
?
2224 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2226 sal_uInt16 nShrinkAgain
= 0;
2227 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2229 // further reduce, like in DrawStrings
2230 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2231 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2232 nNewSize
= bPixelToLogic
?
2233 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2237 // sizes for further processing (alignment etc):
2238 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, bSwap
, nAttrRotate
);
2239 long nPixelWidth
= bPixelToLogic
?
2240 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2241 rNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
2243 else if ( rLeftClip
|| rRightClip
)
2247 long nAvailable
= rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2248 long nScaleSize
= rNeededPixel
- nLeftM
- nRightM
; // without margin
2250 if ( nScaleSize
<= nAvailable
)
2253 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2255 lcl_ScaleFonts( rEngine
, nScale
);
2256 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, false, nAttrRotate
);
2257 long nNewSize
= bPixelToLogic
?
2258 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2260 sal_uInt16 nShrinkAgain
= 0;
2261 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2263 // further reduce, like in DrawStrings
2264 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2265 rEngineWidth
= lcl_GetEditSize( rEngine
, sal_True
, false, nAttrRotate
);
2266 nNewSize
= bPixelToLogic
?
2267 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2270 if ( nNewSize
<= nAvailable
)
2271 rLeftClip
= rRightClip
= false;
2273 // sizes for further processing (alignment etc):
2274 rNeededPixel
= nNewSize
+ nLeftM
+ nRightM
;
2275 rEngineHeight
= lcl_GetEditSize( rEngine
, false, false, nAttrRotate
);
2279 ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr
* pPattern
, const SfxItemSet
* pCondSet
, bool bCellIsValue
) :
2280 meHorJustAttr( lcl_GetValue
<SvxHorJustifyItem
, SvxCellHorJustify
>(*pPattern
, ATTR_HOR_JUSTIFY
, pCondSet
) ),
2281 meHorJustContext( meHorJustAttr
),
2282 meHorJustResult( meHorJustAttr
),
2283 meVerJust( lcl_GetValue
<SvxVerJustifyItem
, SvxCellVerJustify
>(*pPattern
, ATTR_VER_JUSTIFY
, pCondSet
) ),
2284 meHorJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
) ),
2285 meVerJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
) ),
2286 meOrient( pPattern
->GetCellOrientation(pCondSet
) ),
2288 mnX(0), mnY(0), mnCellX(0), mnCellY(0), mnTab(0),
2289 mnPosX(0), mnPosY(0), mnInitPosX(0),
2290 mbBreak( (meHorJustAttr
== SVX_HOR_JUSTIFY_BLOCK
) || lcl_GetBoolValue(*pPattern
, ATTR_LINEBREAK
, pCondSet
) ),
2291 mbCellIsValue(bCellIsValue
),
2292 mbAsianVertical(false),
2293 mbPixelToLogic(false),
2294 mbHyphenatorSet(false),
2296 mpPattern(pPattern
),
2297 mpCondSet(pCondSet
),
2298 mpPreviewFontSet(NULL
),
2301 mpOldPreviewFontSet(NULL
),
2302 mpThisRowInfo(NULL
),
2303 mpMisspellRanges(NULL
)
2306 bool ScOutputData::DrawEditParam::readCellContent(
2307 ScDocument
* pDoc
, bool bShowNullValues
, bool bShowFormulas
, bool bSyntaxMode
, bool bUseStyleColor
, bool bForceAutoColor
, bool& rWrapFields
)
2309 if (maCell
.meType
== CELLTYPE_EDIT
)
2311 const EditTextObject
* pData
= maCell
.mpEditText
;
2314 mpEngine
->SetText(*pData
);
2316 if ( mbBreak
&& !mbAsianVertical
&& pData
->HasField() )
2318 // Fields aren't wrapped, so clipping is enabled to prevent
2319 // a field from being drawn beyond the cell size
2326 OSL_FAIL("pData == 0");
2332 sal_uLong nFormat
= mpPattern
->GetNumberFormat(
2333 pDoc
->GetFormatTable(), mpCondSet
);
2336 ScCellFormat::GetString( maCell
,
2337 nFormat
,aString
, &pColor
,
2338 *pDoc
->GetFormatTable(),
2344 mpEngine
->SetText(aString
);
2345 if ( pColor
&& !bSyntaxMode
&& !( bUseStyleColor
&& bForceAutoColor
) )
2346 lcl_SetEditColor( *mpEngine
, *pColor
);
2349 if (mpMisspellRanges
)
2350 mpEngine
->SetAllMisspellRanges(*mpMisspellRanges
);
2355 void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor
)
2357 // syntax highlighting mode is ignored here
2358 // StringDiffer doesn't look at hyphenate, language items
2360 if (mpPattern
== mpOldPattern
&& mpCondSet
== mpOldCondSet
&& mpPreviewFontSet
== mpOldPreviewFontSet
)
2363 sal_Int32 nConfBackColor
= SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
2364 bool bCellContrast
= bUseStyleColor
&&
2365 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2367 SfxItemSet
* pSet
= new SfxItemSet( mpEngine
->GetEmptyItemSet() );
2368 mpPattern
->FillEditItemSet( pSet
, mpCondSet
);
2369 if ( mpPreviewFontSet
)
2371 const SfxPoolItem
* pItem
;
2372 if ( mpPreviewFontSet
->GetItemState( ATTR_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2374 SvxFontItem
aFontItem(EE_CHAR_FONTINFO
);
2375 aFontItem
= (const SvxFontItem
&)*pItem
;
2376 pSet
->Put( aFontItem
);
2378 if ( mpPreviewFontSet
->GetItemState( ATTR_CJK_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2380 SvxFontItem
aCjkFontItem(EE_CHAR_FONTINFO_CJK
);
2381 aCjkFontItem
= (const SvxFontItem
&)*pItem
;
2382 pSet
->Put( aCjkFontItem
);
2384 if ( mpPreviewFontSet
->GetItemState( ATTR_CTL_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2386 SvxFontItem
aCtlFontItem(EE_CHAR_FONTINFO_CTL
);
2387 aCtlFontItem
= (const SvxFontItem
&)*pItem
;
2388 pSet
->Put( aCtlFontItem
);
2391 mpEngine
->SetDefaults( pSet
);
2392 mpOldPattern
= mpPattern
;
2393 mpOldCondSet
= mpCondSet
;
2394 mpOldPreviewFontSet
= mpPreviewFontSet
;
2396 sal_uLong nControl
= mpEngine
->GetControlWord();
2397 if (meOrient
== SVX_ORIENTATION_STACKED
)
2398 nControl
|= EE_CNTRL_ONECHARPERLINE
;
2400 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
2401 mpEngine
->SetControlWord( nControl
);
2403 if ( !mbHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
2405 // set hyphenator the first time it is needed
2406 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
2407 mpEngine
->SetHyphenator( xXHyphenator
);
2408 mbHyphenatorSet
= true;
2411 Color aBackCol
= ((const SvxBrushItem
&)mpPattern
->GetItem( ATTR_BACKGROUND
, mpCondSet
)).GetColor();
2412 if ( bUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
2413 aBackCol
.SetColor( nConfBackColor
);
2414 mpEngine
->SetBackgroundColor( aBackCol
);
2417 void ScOutputData::DrawEditParam::calcMargins(long& rTopM
, long& rLeftM
, long& rBottomM
, long& rRightM
, double nPPTX
, double nPPTY
) const
2419 const SvxMarginItem
& rMargin
=
2420 static_cast<const SvxMarginItem
&>(mpPattern
->GetItem(ATTR_MARGIN
, mpCondSet
));
2422 sal_uInt16 nIndent
= 0;
2423 if (meHorJustAttr
== SVX_HOR_JUSTIFY_LEFT
|| meHorJustAttr
== SVX_HOR_JUSTIFY_RIGHT
)
2424 nIndent
= lcl_GetValue
<SfxUInt16Item
, sal_uInt16
>(*mpPattern
, ATTR_INDENT
, mpCondSet
);
2426 rLeftM
= static_cast<long>(((rMargin
.GetLeftMargin() + nIndent
) * nPPTX
));
2427 rTopM
= static_cast<long>((rMargin
.GetTopMargin() * nPPTY
));
2428 rRightM
= static_cast<long>((rMargin
.GetRightMargin() * nPPTX
));
2429 rBottomM
= static_cast<long>((rMargin
.GetBottomMargin() * nPPTY
));
2430 if(meHorJustAttr
== SVX_HOR_JUSTIFY_RIGHT
)
2432 rLeftM
= static_cast<long>((rMargin
.GetLeftMargin() * nPPTX
));
2433 rRightM
= static_cast<long>(((rMargin
.GetRightMargin() + nIndent
) * nPPTX
));
2437 void ScOutputData::DrawEditParam::calcPaperSize(
2438 Size
& rPaperSize
, const Rectangle
& rAlignRect
, double nPPTX
, double nPPTY
) const
2440 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2441 calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, nPPTX
, nPPTY
);
2443 if (isVerticallyOriented())
2445 rPaperSize
.Width() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2446 rPaperSize
.Height() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2450 rPaperSize
.Width() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2451 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2454 if (mbAsianVertical
)
2456 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2457 // Subtract some extra value from the height or else the text would go
2458 // outside the cell area. The value of 5 is arbitrary, and is based
2459 // entirely on heuristics.
2460 rPaperSize
.Height() -= 5;
2464 void ScOutputData::DrawEditParam::getEngineSize(ScFieldEditEngine
* pEngine
, long& rWidth
, long& rHeight
) const
2466 long nEngineWidth
= 0;
2467 if (!mbBreak
|| meOrient
== SVX_ORIENTATION_STACKED
|| mbAsianVertical
)
2468 nEngineWidth
= static_cast<long>(pEngine
->CalcTextWidth());
2470 long nEngineHeight
= pEngine
->GetTextHeight();
2472 if (isVerticallyOriented())
2474 long nTemp
= nEngineWidth
;
2475 nEngineWidth
= nEngineHeight
;
2476 nEngineHeight
= nTemp
;
2479 if (meOrient
== SVX_ORIENTATION_STACKED
)
2480 nEngineWidth
= nEngineWidth
* 11 / 10;
2482 rWidth
= nEngineWidth
;
2483 rHeight
= nEngineHeight
;
2486 bool ScOutputData::DrawEditParam::hasLineBreak() const
2488 return (mbBreak
|| (meOrient
== SVX_ORIENTATION_STACKED
) || mbAsianVertical
);
2491 bool ScOutputData::DrawEditParam::isHyperlinkCell() const
2493 if (maCell
.meType
!= CELLTYPE_FORMULA
)
2496 return maCell
.mpFormula
->IsHyperLinkCell();
2499 bool ScOutputData::DrawEditParam::isVerticallyOriented() const
2501 return (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| meOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2504 void ScOutputData::DrawEditParam::calcStartPosForVertical(
2505 Point
& rLogicStart
, long nCellWidth
, long nEngineWidth
, long nTopM
, OutputDevice
* pRefDevice
)
2507 OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
2510 rLogicStart
= pRefDevice
->PixelToLogic(rLogicStart
);
2514 // vertical adjustment is within the EditEngine
2516 rLogicStart
.Y() += pRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
2518 rLogicStart
.Y() += nTopM
;
2520 switch (meHorJustResult
)
2522 case SVX_HOR_JUSTIFY_CENTER
:
2523 rLogicStart
.X() += (nCellWidth
- nEngineWidth
) / 2;
2525 case SVX_HOR_JUSTIFY_RIGHT
:
2526 rLogicStart
.X() += nCellWidth
- nEngineWidth
;
2534 void ScOutputData::DrawEditParam::setAlignmentToEngine()
2536 if (isVerticallyOriented() || mbAsianVertical
)
2538 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2541 case SVX_VER_JUSTIFY_TOP
:
2542 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2543 SVX_ADJUST_LEFT
: SVX_ADJUST_RIGHT
;
2545 case SVX_VER_JUSTIFY_CENTER
:
2546 eSvxAdjust
= SVX_ADJUST_CENTER
;
2548 case SVX_VER_JUSTIFY_BOTTOM
:
2549 case SVX_VER_JUSTIFY_STANDARD
:
2550 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2551 SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
2553 case SVX_VER_JUSTIFY_BLOCK
:
2554 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2558 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2559 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2561 if (meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
2562 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2566 // horizontal alignment now may depend on cell content
2567 // (for values with number formats with mixed script types)
2568 // -> always set adjustment
2570 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2571 if (meOrient
== SVX_ORIENTATION_STACKED
)
2572 eSvxAdjust
= SVX_ADJUST_CENTER
;
2575 if (meOrient
== SVX_ORIENTATION_STANDARD
)
2576 switch (meHorJustResult
)
2578 case SVX_HOR_JUSTIFY_REPEAT
: // repeat is not yet implemented
2579 case SVX_HOR_JUSTIFY_STANDARD
:
2580 assert(!"meHorJustResult does not match getAlignmentFromContext()");
2582 case SVX_HOR_JUSTIFY_LEFT
:
2583 eSvxAdjust
= SVX_ADJUST_LEFT
;
2585 case SVX_HOR_JUSTIFY_CENTER
:
2586 eSvxAdjust
= SVX_ADJUST_CENTER
;
2588 case SVX_HOR_JUSTIFY_RIGHT
:
2589 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2591 case SVX_HOR_JUSTIFY_BLOCK
:
2592 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2598 case SVX_VER_JUSTIFY_TOP
:
2599 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2601 case SVX_VER_JUSTIFY_CENTER
:
2602 eSvxAdjust
= SVX_ADJUST_CENTER
;
2604 case SVX_VER_JUSTIFY_BOTTOM
:
2605 case SVX_VER_JUSTIFY_STANDARD
:
2606 eSvxAdjust
= SVX_ADJUST_LEFT
;
2608 case SVX_VER_JUSTIFY_BLOCK
:
2609 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2614 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2616 if (mbAsianVertical
)
2618 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2619 if (meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
2620 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2624 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod
, EE_PARA_JUST_METHOD
) );
2625 if (meVerJust
== SVX_VER_JUSTIFY_BLOCK
)
2626 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2630 mpEngine
->SetVertical(mbAsianVertical
);
2631 if (maCell
.meType
== CELLTYPE_EDIT
)
2633 // We need to synchronize the vertical mode in the EditTextObject
2634 // instance too. No idea why we keep this state in two separate
2636 const EditTextObject
* pData
= maCell
.mpEditText
;
2638 const_cast<EditTextObject
*>(pData
)->SetVertical(mbAsianVertical
);
2642 bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine
* pEngine
)
2644 if (meHorJustResult
== SVX_HOR_JUSTIFY_RIGHT
|| meHorJustResult
== SVX_HOR_JUSTIFY_CENTER
)
2646 SvxAdjust eEditAdjust
= (meHorJustResult
== SVX_HOR_JUSTIFY_CENTER
) ?
2647 SVX_ADJUST_CENTER
: SVX_ADJUST_RIGHT
;
2649 pEngine
->SetUpdateMode(false);
2650 pEngine
->SetDefaultItem( SvxAdjustItem(eEditAdjust
, EE_PARA_JUST
) );
2651 pEngine
->SetUpdateMode(true);
2657 void ScOutputData::DrawEditParam::adjustForRTL()
2659 if (!mpEngine
->IsRightToLeft(0))
2663 // For right-to-left, EditEngine always calculates its lines
2664 // beginning from the right edge, but EditLine::nStartPosX is
2665 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
2666 Size aLogicPaper
= mpEngine
->GetPaperSize();
2667 if ( aLogicPaper
.Width() > USHRT_MAX
)
2669 aLogicPaper
.Width() = USHRT_MAX
;
2670 mpEngine
->SetPaperSize(aLogicPaper
);
2674 void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart
, OutputDevice
* pDev
)
2676 // PDF: whole-cell hyperlink from formula?
2677 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
2678 bool bHasURL
= pPDFData
&& isHyperlinkCell();
2682 long nURLWidth
= (long) mpEngine
->CalcTextWidth();
2683 long nURLHeight
= mpEngine
->GetTextHeight();
2686 Size aPaper
= mpEngine
->GetPaperSize();
2687 if ( mbAsianVertical
)
2688 nURLHeight
= aPaper
.Height();
2690 nURLWidth
= aPaper
.Width();
2692 if (isVerticallyOriented())
2693 std::swap( nURLWidth
, nURLHeight
);
2694 else if (mbAsianVertical
)
2695 aURLStart
.X() -= nURLWidth
;
2697 Rectangle
aURLRect( aURLStart
, Size( nURLWidth
, nURLHeight
) );
2698 lcl_DoHyperlinkResult(pDev
, aURLRect
, maCell
);
2701 void ScOutputData::DrawEditStandard(DrawEditParam
& rParam
)
2703 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
2704 OSL_ASSERT(!rParam
.mbAsianVertical
);
2706 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
2708 bool bHidden
= false;
2709 bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
2710 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
2711 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
2713 if ( rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
)
2715 // ignore orientation/rotation if "repeat" is active
2716 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
2719 // #i31843# "repeat" with "line breaks" is treated as default alignment
2720 // (but rotation is still disabled).
2721 // Default again leads to context dependent alignment instead of
2722 // SVX_HOR_JUSTIFY_STANDARD.
2723 if ( rParam
.mbBreak
)
2724 rParam
.meHorJustResult
= rParam
.meHorJustContext
;
2729 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2730 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2731 bHidden
= true; // gedreht wird getrennt ausgegeben
2737 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
2739 //! mirror margin values for RTL?
2740 //! move margin down to after final GetOutputArea call
2741 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2742 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
2744 SCCOL nXForPos
= rParam
.mnX
;
2745 if ( nXForPos
< nX1
)
2748 rParam
.mnPosX
= rParam
.mnInitPosX
;
2750 SCSIZE nArrYForPos
= rParam
.mnArrY
;
2751 if ( nArrYForPos
< 1 )
2754 rParam
.mnPosY
= nScrY
;
2757 OutputAreaParam aAreaParam
;
2760 // Initial page size - large for normal text, cell size for automatic line breaks
2763 Size aPaperSize
= Size( 1000000, 1000000 );
2766 // call GetOutputArea with nNeeded=0, to get only the cell width
2768 //! handle nArrY == 0
2769 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
2770 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2771 rParam
.mbCellIsValue
, true, false, aAreaParam
);
2773 //! special ScEditUtil handling if formatting for printer
2774 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
2776 if (rParam
.mbPixelToLogic
)
2778 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
2779 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
2781 // #i85342# screen display and formatting for printer,
2782 // use same GetEditArea call as in ScViewData::SetEditEngine
2784 Fraction
aFract(1,1);
2785 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
2786 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
2787 aLogicSize
.Width() = aUtilRect
.GetWidth();
2789 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
2792 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2795 // Fill the EditEngine (cell attributes and text)
2798 // default alignment for asian vertical mode is top-right
2799 if ( rParam
.mbAsianVertical
&& rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
2800 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
2802 rParam
.setPatternToEngine(mbUseStyleColor
);
2803 rParam
.setAlignmentToEngine();
2805 // Read content from cell
2807 bool bWrapFields
= false;
2808 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
2809 // Failed to read cell content. Bail out.
2813 SetEditSyntaxColor(*rParam
.mpEngine
, rParam
.maCell
);
2814 else if ( mbUseStyleColor
&& mbForceAutoColor
)
2815 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
2817 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
2820 // Get final output area using the calculated width
2823 long nEngineWidth
, nEngineHeight
;
2824 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
2826 long nNeededPixel
= nEngineWidth
;
2827 if (rParam
.mbPixelToLogic
)
2828 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
2829 nNeededPixel
+= nLeftM
+ nRightM
;
2831 if (!rParam
.mbBreak
|| bShrink
)
2833 // for break, the first GetOutputArea call is sufficient
2834 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
2835 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2836 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
2840 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
2841 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
2842 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
2843 nEngineWidth
, nEngineHeight
, nNeededPixel
,
2844 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
2846 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
2848 // First check if twice the space for the formatted text is available
2849 // (otherwise just keep it unchanged).
2851 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
2852 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
2853 if ( nAvailable
>= 2 * nFormatted
)
2855 // "repeat" is handled with unformatted text (for performance reasons)
2856 OUString aCellStr
= rParam
.mpEngine
->GetText();
2857 rParam
.mpEngine
->SetText( aCellStr
);
2859 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
2860 if (rParam
.mbPixelToLogic
)
2861 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
2862 if ( pFmtDevice
!= mpRefDevice
)
2864 if ( nRepeatSize
> 0 )
2866 long nRepeatCount
= nAvailable
/ nRepeatSize
;
2867 if ( nRepeatCount
> 1 )
2869 OUString aRepeated
= aCellStr
;
2870 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
2871 aRepeated
+= aCellStr
;
2872 rParam
.mpEngine
->SetText( aRepeated
);
2874 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
2875 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2876 if (rParam
.mbPixelToLogic
)
2877 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2879 nNeededPixel
= nEngineWidth
;
2880 nNeededPixel
+= nLeftM
+ nRightM
;
2886 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
2888 rParam
.mpEngine
->SetText(OUString("###"));
2889 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2890 if (rParam
.mbPixelToLogic
)
2891 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2893 nNeededPixel
= nEngineWidth
;
2894 nNeededPixel
+= nLeftM
+ nRightM
;
2896 // No clip marks if "###" doesn't fit (same as in DrawStrings)
2899 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
2901 aPaperSize
.Width() = nNeededPixel
+ 1;
2902 if (rParam
.mbPixelToLogic
)
2903 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
2905 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2909 long nStartX
= aAreaParam
.maAlignRect
.Left();
2910 long nStartY
= aAreaParam
.maAlignRect
.Top();
2911 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
2912 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
2913 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
2917 // text with automatic breaks is aligned only within the
2918 // edit engine's paper size, the output of the whole area
2919 // is always left-aligned
2925 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
2926 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
2927 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
2928 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
2933 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
2937 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
2939 aAreaParam
.maClipRect
.Left() = nScrX
;
2940 aAreaParam
.mbLeftClip
= true;
2942 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
2944 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
2945 aAreaParam
.mbRightClip
= true;
2948 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
2949 bool bSimClip
= false;
2953 // Fields in a cell with automatic breaks: clip to cell width
2957 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
2959 aAreaParam
.maClipRect
.Top() = nScrY
;
2962 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
2964 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
2968 Size aCellSize
; // output area, excluding margins, in logical units
2969 if (rParam
.mbPixelToLogic
)
2970 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
2972 aCellSize
= Size( nOutWidth
, nOutHeight
);
2974 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
2976 const ScMergeAttr
* pMerge
=
2977 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
2978 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
2980 // Don't clip for text height when printing rows with optimal height,
2981 // except when font size is from conditional formatting.
2982 //! Allow clipping when vertically merged?
2983 if ( eType
!= OUTTYPE_PRINTER
||
2984 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
2985 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
2986 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
2991 // Show clip marks if height is at least 5pt too small and
2992 // there are several lines of text.
2993 // Not for asian vertical text, because that would interfere
2994 // with the default right position of the text.
2995 // Only with automatic line breaks, to avoid having to find
2996 // the cells with the horizontal end of the text again.
2997 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
2998 rParam
.mbBreak
&& bMarkClipped
&&
2999 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3001 CellInfo
* pClipMarkCell
= NULL
;
3004 // anywhere in the merged area...
3005 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3006 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3009 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3011 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3014 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
3015 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3016 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3020 Rectangle aLogicClip
;
3021 if (bClip
|| bSimClip
)
3023 // Clip marks are already handled in GetOutputArea
3025 if (rParam
.mbPixelToLogic
)
3026 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3028 aLogicClip
= aAreaParam
.maClipRect
;
3030 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3035 mpDev
->IntersectClipRegion( aLogicClip
);
3038 mpDev
->SetClipRegion( Region( aLogicClip
) );
3043 if (rParam
.mbPixelToLogic
)
3044 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
3046 aLogicStart
= Point(nStartX
, nStartY
);
3048 if (!rParam
.mbBreak
)
3050 // horizontal alignment
3051 if (rParam
.adjustHorAlignment(rParam
.mpEngine
))
3052 // reset adjustment for the next cell
3053 rParam
.mpOldPattern
= NULL
;
3056 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
3057 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
3059 //! if pRefDevice != pFmtDevice, keep heights in logic units,
3060 //! only converting margin?
3062 if (rParam
.mbPixelToLogic
)
3063 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
3064 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3065 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
3068 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
3070 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
3072 if (rParam
.mbPixelToLogic
)
3073 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
3074 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3075 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
3078 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
3082 if (rParam
.mbPixelToLogic
)
3083 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3085 aLogicStart
.Y() += nTopM
;
3088 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3090 rParam
.adjustForRTL();
3092 // bMoveClipped handling has been replaced by complete alignment
3093 // handling (also extending to the left).
3097 // kein hartes Clipping, aber nur die betroffenen
3100 Point aDocStart
= aLogicClip
.TopLeft();
3101 aDocStart
-= aLogicStart
;
3102 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
3106 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
3114 mpDev
->SetClipRegion();
3117 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3120 void ScOutputData::ShowClipMarks( DrawEditParam
& rParam
, long nEngineHeight
, const Size
& aCellSize
,
3121 bool bMerged
, OutputAreaParam
& aAreaParam
)
3123 // Show clip marks if height is at least 5pt too small and
3124 // there are several lines of text.
3125 // Not for asian vertical text, because that would interfere
3126 // with the default right position of the text.
3127 // Only with automatic line breaks, to avoid having to find
3128 // the cells with the horizontal end of the text again.
3129 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
3130 rParam
.mbBreak
&& bMarkClipped
&&
3131 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3133 CellInfo
* pClipMarkCell
= NULL
;
3136 // anywhere in the merged area...
3137 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3138 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3141 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3143 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3146 const long nMarkPixel
= static_cast<long>( SC_CLIPMARK_SIZE
* mnPPTX
);
3147 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3148 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3152 bool ScOutputData::Clip( DrawEditParam
& rParam
, const Size
& aCellSize
,
3153 OutputAreaParam
& aAreaParam
, long nEngineHeight
,
3156 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3158 aAreaParam
.maClipRect
.Left() = nScrX
;
3159 aAreaParam
.mbLeftClip
= true;
3161 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3163 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3164 aAreaParam
.mbRightClip
= true;
3167 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3168 bool bSimClip
= false;
3172 // Fields in a cell with automatic breaks: clip to cell width
3176 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3178 aAreaParam
.maClipRect
.Top() = nScrY
;
3181 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3183 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3187 const Size
& aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3188 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
3190 const ScMergeAttr
* pMerge
=
3191 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
3192 const bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
3194 // Don't clip for text height when printing rows with optimal height,
3195 // except when font size is from conditional formatting.
3196 //! Allow clipping when vertically merged?
3197 if ( eType
!= OUTTYPE_PRINTER
||
3198 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
3199 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
3200 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
3205 ShowClipMarks( rParam
, nEngineHeight
, aCellSize
, bMerged
, aAreaParam
);
3208 Rectangle aLogicClip
;
3209 if (bClip
|| bSimClip
)
3211 // Clip marks are already handled in GetOutputArea
3213 if (rParam
.mbPixelToLogic
)
3214 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3216 aLogicClip
= aAreaParam
.maClipRect
;
3218 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3223 mpDev
->IntersectClipRegion( aLogicClip
);
3226 mpDev
->SetClipRegion( Region( aLogicClip
) );
3233 void ScOutputData::DrawEditBottomTop(DrawEditParam
& rParam
)
3235 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3237 const bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3238 const bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3240 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3242 //! mirror margin values for RTL?
3243 //! move margin down to after final GetOutputArea call
3244 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3245 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3247 SCCOL nXForPos
= rParam
.mnX
;
3248 if ( nXForPos
< nX1
)
3251 rParam
.mnPosX
= rParam
.mnInitPosX
;
3253 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3254 if ( nArrYForPos
< 1 )
3257 rParam
.mnPosY
= nScrY
;
3260 OutputAreaParam aAreaParam
;
3263 // Initial page size - large for normal text, cell size for automatic line breaks
3266 Size aPaperSize
= Size( 1000000, 1000000 );
3269 // call GetOutputArea with nNeeded=0, to get only the cell width
3271 //! handle nArrY == 0
3272 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3273 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3274 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3276 //! special ScEditUtil handling if formatting for printer
3277 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3279 if (rParam
.mbPixelToLogic
)
3281 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3282 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3285 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3288 // Fill the EditEngine (cell attributes and text)
3291 rParam
.setPatternToEngine(mbUseStyleColor
);
3292 rParam
.setAlignmentToEngine();
3294 // Read content from cell
3296 bool bWrapFields
= false;
3297 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3298 // Failed to read cell content. Bail out.
3302 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3303 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3304 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3306 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3309 // Get final output area using the calculated width
3312 long nEngineWidth
, nEngineHeight
;
3313 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3315 long nNeededPixel
= nEngineWidth
;
3316 if (rParam
.mbPixelToLogic
)
3317 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3318 nNeededPixel
+= nLeftM
+ nRightM
;
3320 if (!rParam
.mbBreak
|| bShrink
)
3322 // for break, the first GetOutputArea call is sufficient
3323 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3324 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3325 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3329 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3330 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3331 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3332 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3333 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3335 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3337 // First check if twice the space for the formatted text is available
3338 // (otherwise just keep it unchanged).
3340 const long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3341 const long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3342 if ( nAvailable
>= 2 * nFormatted
)
3344 // "repeat" is handled with unformatted text (for performance reasons)
3345 OUString aCellStr
= rParam
.mpEngine
->GetText();
3346 rParam
.mpEngine
->SetText( aCellStr
);
3348 long nRepeatSize
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3349 if (rParam
.mbPixelToLogic
)
3350 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3351 if ( pFmtDevice
!= mpRefDevice
)
3353 if ( nRepeatSize
> 0 )
3355 const long nRepeatCount
= nAvailable
/ nRepeatSize
;
3356 if ( nRepeatCount
> 1 )
3358 OUString aRepeated
= aCellStr
;
3359 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3360 aRepeated
+= aCellStr
;
3361 rParam
.mpEngine
->SetText( aRepeated
);
3363 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3364 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3365 if (rParam
.mbPixelToLogic
)
3366 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3368 nNeededPixel
= nEngineWidth
;
3369 nNeededPixel
+= nLeftM
+ nRightM
;
3375 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3377 rParam
.mpEngine
->SetText(OUString("###"));
3378 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3379 if (rParam
.mbPixelToLogic
)
3380 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3382 nNeededPixel
= nEngineWidth
;
3383 nNeededPixel
+= nLeftM
+ nRightM
;
3385 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3389 long nStartX
= aAreaParam
.maAlignRect
.Left();
3390 const long nStartY
= aAreaParam
.maAlignRect
.Top();
3391 const long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3392 const long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3393 const long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3397 // text with automatic breaks is aligned only within the
3398 // edit engine's paper size, the output of the whole area
3399 // is always left-aligned
3405 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3406 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3407 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3408 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3413 const bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3417 // output area, excluding margins, in logical units
3418 const Size
& aCellSize
= rParam
.mbPixelToLogic
3419 ? mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) )
3420 : Size( nOutWidth
, nOutHeight
);
3422 const bool bClip
= Clip( rParam
, aCellSize
, aAreaParam
, nEngineHeight
, bWrapFields
);
3424 Point
aLogicStart(nStartX
, nStartY
);
3425 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3427 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3429 if (rParam
.meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
|| rParam
.mbBreak
)
3431 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3432 aPSize
.Width() = aCellSize
.Height();
3433 rParam
.mpEngine
->SetPaperSize(aPSize
);
3435 rParam
.mbBreak
? aPSize
.Width() : nEngineHeight
;
3439 // Note that the "paper" is rotated 90 degrees to the left, so
3440 // paper's width is in vertical direction. Also, the whole text
3441 // is on a single line, as text wrap is not in effect.
3443 // Set the paper width to be the width of the text.
3444 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3445 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3446 rParam
.mpEngine
->SetPaperSize(aPSize
);
3449 long nTopOffset
= 0;
3450 if (rParam
.mbPixelToLogic
)
3452 nGap
= mpRefDevice
->LogicToPixel(aCellSize
).Height() - mpRefDevice
->LogicToPixel(aPSize
).Width();
3453 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3454 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3458 nGap
= aCellSize
.Height() - aPSize
.Width();
3462 // First, align text to bottom.
3463 aLogicStart
.Y() += aCellSize
.Height();
3464 aLogicStart
.Y() += nTopOffset
;
3466 switch (rParam
.meVerJust
)
3468 case SVX_VER_JUSTIFY_STANDARD
:
3469 case SVX_VER_JUSTIFY_BOTTOM
:
3470 // align to bottom (do nothing).
3472 case SVX_VER_JUSTIFY_CENTER
:
3474 aLogicStart
.Y() -= nGap
/ 2;
3476 case SVX_VER_JUSTIFY_BLOCK
:
3477 case SVX_VER_JUSTIFY_TOP
:
3479 aLogicStart
.Y() -= nGap
;
3485 rParam
.adjustForRTL();
3486 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 900);
3493 mpDev
->SetClipRegion();
3496 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3499 void ScOutputData::DrawEditTopBottom(DrawEditParam
& rParam
)
3501 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3503 const bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3504 const bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3506 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3508 //! mirror margin values for RTL?
3509 //! move margin down to after final GetOutputArea call
3510 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3511 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3513 SCCOL nXForPos
= rParam
.mnX
;
3514 if ( nXForPos
< nX1
)
3517 rParam
.mnPosX
= rParam
.mnInitPosX
;
3519 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3520 if ( nArrYForPos
< 1 )
3523 rParam
.mnPosY
= nScrY
;
3526 OutputAreaParam aAreaParam
;
3529 // Initial page size - large for normal text, cell size for automatic line breaks
3532 Size aPaperSize
= Size( 1000000, 1000000 );
3533 if (rParam
.hasLineBreak())
3535 // call GetOutputArea with nNeeded=0, to get only the cell width
3537 //! handle nArrY == 0
3538 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3539 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3540 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3542 //! special ScEditUtil handling if formatting for printer
3543 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3545 if (rParam
.mbPixelToLogic
)
3547 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3548 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3551 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3554 // Fill the EditEngine (cell attributes and text)
3557 rParam
.setPatternToEngine(mbUseStyleColor
);
3558 rParam
.setAlignmentToEngine();
3560 // Read content from cell
3562 bool bWrapFields
= false;
3563 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3564 // Failed to read cell content. Bail out.
3568 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3569 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3570 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3572 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3575 // Get final output area using the calculated width
3578 long nEngineWidth
, nEngineHeight
;
3579 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3581 long nNeededPixel
= nEngineWidth
;
3582 if (rParam
.mbPixelToLogic
)
3583 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3584 nNeededPixel
+= nLeftM
+ nRightM
;
3586 if (!rParam
.mbBreak
|| bShrink
)
3588 // for break, the first GetOutputArea call is sufficient
3589 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3590 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3591 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3595 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3596 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3597 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3598 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3599 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3601 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3603 // First check if twice the space for the formatted text is available
3604 // (otherwise just keep it unchanged).
3606 const long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3607 const long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3608 if ( nAvailable
>= 2 * nFormatted
)
3610 // "repeat" is handled with unformatted text (for performance reasons)
3611 OUString aCellStr
= rParam
.mpEngine
->GetText();
3612 rParam
.mpEngine
->SetText( aCellStr
);
3614 long nRepeatSize
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3615 if (rParam
.mbPixelToLogic
)
3616 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3617 if ( pFmtDevice
!= mpRefDevice
)
3619 if ( nRepeatSize
> 0 )
3621 const long nRepeatCount
= nAvailable
/ nRepeatSize
;
3622 if ( nRepeatCount
> 1 )
3624 OUString aRepeated
= aCellStr
;
3625 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3626 aRepeated
+= aCellStr
;
3627 rParam
.mpEngine
->SetText( aRepeated
);
3629 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3630 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3631 if (rParam
.mbPixelToLogic
)
3632 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3634 nNeededPixel
= nEngineWidth
;
3635 nNeededPixel
+= nLeftM
+ nRightM
;
3641 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3643 rParam
.mpEngine
->SetText(OUString("###"));
3644 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3645 if (rParam
.mbPixelToLogic
)
3646 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3648 nNeededPixel
= nEngineWidth
;
3649 nNeededPixel
+= nLeftM
+ nRightM
;
3651 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3655 long nStartX
= aAreaParam
.maAlignRect
.Left();
3656 const long nStartY
= aAreaParam
.maAlignRect
.Top();
3657 const long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3658 const long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3659 const long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3663 // text with automatic breaks is aligned only within the
3664 // edit engine's paper size, the output of the whole area
3665 // is always left-aligned
3668 if (rParam
.meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
3669 nStartX
+= aPaperSize
.Height();
3673 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3674 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3675 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3676 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3681 const bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3685 // output area, excluding margins, in logical units
3686 const Size
& aCellSize
= rParam
.mbPixelToLogic
3687 ? mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) )
3688 : Size( nOutWidth
, nOutHeight
);
3690 const bool bClip
= Clip( rParam
, aCellSize
, aAreaParam
, nEngineHeight
, bWrapFields
);
3692 Point
aLogicStart(nStartX
, nStartY
);
3693 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3695 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3697 if (rParam
.meHorJustResult
!= SVX_HOR_JUSTIFY_BLOCK
)
3699 aLogicStart
.X() += nEngineWidth
;
3700 if (!rParam
.mbBreak
)
3702 // Set the paper width to text size.
3703 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3704 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3705 rParam
.mpEngine
->SetPaperSize(aPSize
);
3708 long nTopOffset
= 0; // offset by top margin
3709 if (rParam
.mbPixelToLogic
)
3711 nGap
= mpRefDevice
->LogicToPixel(aPSize
).Width() - mpRefDevice
->LogicToPixel(aCellSize
).Height();
3712 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3713 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3717 nGap
= aPSize
.Width() - aCellSize
.Height();
3720 aLogicStart
.Y() += nTopOffset
;
3722 switch (rParam
.meVerJust
)
3724 case SVX_VER_JUSTIFY_STANDARD
:
3725 case SVX_VER_JUSTIFY_BOTTOM
:
3727 aLogicStart
.Y() -= nGap
;
3729 case SVX_VER_JUSTIFY_CENTER
:
3731 aLogicStart
.Y() -= nGap
/ 2;
3733 case SVX_VER_JUSTIFY_BLOCK
:
3734 case SVX_VER_JUSTIFY_TOP
:
3735 // align to top (do nothing)
3742 rParam
.adjustForRTL();
3744 // bMoveClipped handling has been replaced by complete alignment
3745 // handling (also extending to the left).
3747 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 2700);
3754 mpDev
->SetClipRegion();
3757 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3760 void ScOutputData::DrawEditStacked(DrawEditParam
& rParam
)
3762 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3763 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3765 bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3766 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3768 rParam
.mbAsianVertical
=
3769 lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_VERTICAL_ASIAN
, rParam
.mpCondSet
);
3771 if ( rParam
.mbAsianVertical
)
3773 // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
3774 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
3775 DrawEditAsianVertical(rParam
);
3779 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3781 //! mirror margin values for RTL?
3782 //! move margin down to after final GetOutputArea call
3783 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3784 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3786 SCCOL nXForPos
= rParam
.mnX
;
3787 if ( nXForPos
< nX1
)
3790 rParam
.mnPosX
= rParam
.mnInitPosX
;
3792 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3793 if ( nArrYForPos
< 1 )
3796 rParam
.mnPosY
= nScrY
;
3799 OutputAreaParam aAreaParam
;
3802 // Initial page size - large for normal text, cell size for automatic line breaks
3805 Size aPaperSize
= Size( 1000000, 1000000 );
3806 // call GetOutputArea with nNeeded=0, to get only the cell width
3808 //! handle nArrY == 0
3809 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3810 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3811 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3813 //! special ScEditUtil handling if formatting for printer
3814 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3816 if (rParam
.mbPixelToLogic
)
3818 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3819 if ( rParam
.mbBreak
&& mpRefDevice
!= pFmtDevice
)
3821 // #i85342# screen display and formatting for printer,
3822 // use same GetEditArea call as in ScViewData::SetEditEngine
3824 Fraction
aFract(1,1);
3825 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
3826 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
3827 aLogicSize
.Width() = aUtilRect
.GetWidth();
3829 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3832 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3835 // Fill the EditEngine (cell attributes and text)
3838 rParam
.setPatternToEngine(mbUseStyleColor
);
3839 rParam
.setAlignmentToEngine();
3841 // Read content from cell
3843 bool bWrapFields
= false;
3844 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3845 // Failed to read cell content. Bail out.
3849 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3850 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3851 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3853 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3856 // Get final output area using the calculated width
3859 long nEngineWidth
, nEngineHeight
;
3860 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3862 long nNeededPixel
= nEngineWidth
;
3863 if (rParam
.mbPixelToLogic
)
3864 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3865 nNeededPixel
+= nLeftM
+ nRightM
;
3869 // for break, the first GetOutputArea call is sufficient
3870 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3871 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3872 true, false, false, aAreaParam
);
3874 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3875 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
3876 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3877 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3878 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3880 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3882 // First check if twice the space for the formatted text is available
3883 // (otherwise just keep it unchanged).
3885 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3886 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3887 if ( nAvailable
>= 2 * nFormatted
)
3889 // "repeat" is handled with unformatted text (for performance reasons)
3890 OUString aCellStr
= rParam
.mpEngine
->GetText();
3891 rParam
.mpEngine
->SetText( aCellStr
);
3893 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
3894 if (rParam
.mbPixelToLogic
)
3895 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3896 if ( pFmtDevice
!= mpRefDevice
)
3898 if ( nRepeatSize
> 0 )
3900 long nRepeatCount
= nAvailable
/ nRepeatSize
;
3901 if ( nRepeatCount
> 1 )
3903 OUString aRepeated
= aCellStr
;
3904 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3905 aRepeated
+= aCellStr
;
3906 rParam
.mpEngine
->SetText( aRepeated
);
3908 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3909 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3910 if (rParam
.mbPixelToLogic
)
3911 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3913 nNeededPixel
= nEngineWidth
;
3914 nNeededPixel
+= nLeftM
+ nRightM
;
3920 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3922 rParam
.mpEngine
->SetText(OUString("###"));
3923 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3924 if (rParam
.mbPixelToLogic
)
3925 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3927 nNeededPixel
= nEngineWidth
;
3928 nNeededPixel
+= nLeftM
+ nRightM
;
3930 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3933 if ( eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
3935 aPaperSize
.Width() = nNeededPixel
+ 1;
3936 if (rParam
.mbPixelToLogic
)
3937 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
3939 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3943 long nStartX
= aAreaParam
.maAlignRect
.Left();
3944 long nStartY
= aAreaParam
.maAlignRect
.Top();
3945 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3946 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3947 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3951 // text with automatic breaks is aligned only within the
3952 // edit engine's paper size, the output of the whole area
3953 // is always left-aligned
3959 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3960 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3961 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3962 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3967 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3971 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3973 aAreaParam
.maClipRect
.Left() = nScrX
;
3974 aAreaParam
.mbLeftClip
= true;
3976 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3978 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3979 aAreaParam
.mbRightClip
= true;
3982 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3983 bool bSimClip
= false;
3987 // Fields in a cell with automatic breaks: clip to cell width
3991 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3993 aAreaParam
.maClipRect
.Top() = nScrY
;
3996 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3998 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
4002 Size aCellSize
; // output area, excluding margins, in logical units
4003 if (rParam
.mbPixelToLogic
)
4004 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4006 aCellSize
= Size( nOutWidth
, nOutHeight
);
4008 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4010 const ScMergeAttr
* pMerge
=
4011 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4012 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4014 // Don't clip for text height when printing rows with optimal height,
4015 // except when font size is from conditional formatting.
4016 //! Allow clipping when vertically merged?
4017 if ( eType
!= OUTTYPE_PRINTER
||
4018 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4019 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4020 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4025 // Show clip marks if height is at least 5pt too small and
4026 // there are several lines of text.
4027 // Not for asian vertical text, because that would interfere
4028 // with the default right position of the text.
4029 // Only with automatic line breaks, to avoid having to find
4030 // the cells with the horizontal end of the text again.
4031 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4032 rParam
.mbBreak
&& bMarkClipped
&&
4033 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4035 CellInfo
* pClipMarkCell
= NULL
;
4038 // anywhere in the merged area...
4039 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4040 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4043 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4045 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4048 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4049 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4050 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4054 Rectangle aLogicClip
;
4055 if (bClip
|| bSimClip
)
4057 // Clip marks are already handled in GetOutputArea
4059 if (rParam
.mbPixelToLogic
)
4060 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4062 aLogicClip
= aAreaParam
.maClipRect
;
4064 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4069 mpDev
->IntersectClipRegion( aLogicClip
);
4072 mpDev
->SetClipRegion( Region( aLogicClip
) );
4077 if (rParam
.mbPixelToLogic
)
4078 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4080 aLogicStart
= Point(nStartX
, nStartY
);
4082 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
4083 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
4085 //! if pRefDevice != pFmtDevice, keep heights in logic units,
4086 //! only converting margin?
4088 if (rParam
.mbPixelToLogic
)
4089 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
4090 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4091 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
4094 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
4096 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
4098 if (rParam
.mbPixelToLogic
)
4099 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
4100 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4101 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
4104 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
4108 if (rParam
.mbPixelToLogic
)
4109 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4111 aLogicStart
.Y() += nTopM
;
4114 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4116 Size aPaperLogic
= rParam
.mpEngine
->GetPaperSize();
4117 aPaperLogic
.Width() = nEngineWidth
;
4118 rParam
.mpEngine
->SetPaperSize(aPaperLogic
);
4120 rParam
.adjustForRTL();
4122 // bMoveClipped handling has been replaced by complete alignment
4123 // handling (also extending to the left).
4127 // kein hartes Clipping, aber nur die betroffenen
4130 Point aDocStart
= aLogicClip
.TopLeft();
4131 aDocStart
-= aLogicStart
;
4132 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
4136 rParam
.mpEngine
->Draw( mpDev
, aLogicStart
, 0 );
4144 mpDev
->SetClipRegion();
4147 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4150 void ScOutputData::DrawEditAsianVertical(DrawEditParam
& rParam
)
4152 // When in asian vertical orientation, the orientation value is STANDARD,
4153 // and the asian vertical boolean is true.
4154 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
4155 OSL_ASSERT(rParam
.mbAsianVertical
);
4156 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
4158 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
4160 bool bHidden
= false;
4161 bool bRepeat
= false;
4162 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
4163 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
4167 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
4168 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
4169 bHidden
= true; // gedreht wird getrennt ausgegeben
4172 // default alignment for asian vertical mode is top-right
4173 /* TODO: is setting meHorJustContext and meHorJustResult unconditionally to
4174 * SVX_HOR_JUSTIFY_RIGHT really wanted? Seems this was done all the time,
4175 * also before context was introduced and everything was attr only. */
4176 if ( rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_STANDARD
)
4177 rParam
.meHorJustResult
= rParam
.meHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
4182 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
4184 //! mirror margin values for RTL?
4185 //! move margin down to after final GetOutputArea call
4186 long nTopM
, nLeftM
, nBottomM
, nRightM
;
4187 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
4189 SCCOL nXForPos
= rParam
.mnX
;
4190 if ( nXForPos
< nX1
)
4193 rParam
.mnPosX
= rParam
.mnInitPosX
;
4195 SCSIZE nArrYForPos
= rParam
.mnArrY
;
4196 if ( nArrYForPos
< 1 )
4199 rParam
.mnPosY
= nScrY
;
4202 OutputAreaParam aAreaParam
;
4205 // Initial page size - large for normal text, cell size for automatic line breaks
4208 Size aPaperSize
= Size( 1000000, 1000000 );
4209 // call GetOutputArea with nNeeded=0, to get only the cell width
4211 //! handle nArrY == 0
4212 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
4213 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4214 rParam
.mbCellIsValue
, true, false, aAreaParam
);
4216 //! special ScEditUtil handling if formatting for printer
4217 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
4219 if (rParam
.mbPixelToLogic
)
4221 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
4222 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
4224 // #i85342# screen display and formatting for printer,
4225 // use same GetEditArea call as in ScViewData::SetEditEngine
4227 Fraction
aFract(1,1);
4228 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
4229 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
4230 aLogicSize
.Width() = aUtilRect
.GetWidth();
4232 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
4235 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4238 // Fill the EditEngine (cell attributes and text)
4241 // default alignment for asian vertical mode is top-right
4242 if ( rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
4243 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
4245 rParam
.setPatternToEngine(mbUseStyleColor
);
4246 rParam
.setAlignmentToEngine();
4248 // Read content from cell
4250 bool bWrapFields
= false;
4251 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
4252 // Failed to read cell content. Bail out.
4256 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
4257 else if ( mbUseStyleColor
&& mbForceAutoColor
)
4258 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
4260 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
4263 // Get final output area using the calculated width
4266 long nEngineWidth
, nEngineHeight
;
4267 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
4269 long nNeededPixel
= nEngineWidth
;
4270 if (rParam
.mbPixelToLogic
)
4271 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
4272 nNeededPixel
+= nLeftM
+ nRightM
;
4274 // for break, the first GetOutputArea call is sufficient
4275 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
4276 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4277 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
4281 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
4282 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
4283 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
4284 nEngineWidth
, nEngineHeight
, nNeededPixel
,
4285 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
4287 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
4289 // First check if twice the space for the formatted text is available
4290 // (otherwise just keep it unchanged).
4292 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
4293 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
4294 if ( nAvailable
>= 2 * nFormatted
)
4296 // "repeat" is handled with unformatted text (for performance reasons)
4297 OUString aCellStr
= rParam
.mpEngine
->GetText();
4298 rParam
.mpEngine
->SetText( aCellStr
);
4300 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
4301 if (rParam
.mbPixelToLogic
)
4302 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
4303 if ( pFmtDevice
!= mpRefDevice
)
4305 if ( nRepeatSize
> 0 )
4307 long nRepeatCount
= nAvailable
/ nRepeatSize
;
4308 if ( nRepeatCount
> 1 )
4310 OUString aRepeated
= aCellStr
;
4311 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
4312 aRepeated
+= aCellStr
;
4313 rParam
.mpEngine
->SetText( aRepeated
);
4315 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
4316 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
4317 if (rParam
.mbPixelToLogic
)
4318 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
4320 nNeededPixel
= nEngineWidth
;
4321 nNeededPixel
+= nLeftM
+ nRightM
;
4327 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
4329 rParam
.mpEngine
->SetText(OUString("###"));
4330 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
4331 if (rParam
.mbPixelToLogic
)
4332 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
4334 nNeededPixel
= nEngineWidth
;
4335 nNeededPixel
+= nLeftM
+ nRightM
;
4337 // No clip marks if "###" doesn't fit (same as in DrawStrings)
4340 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
4342 aPaperSize
.Width() = nNeededPixel
+ 1;
4343 if (rParam
.mbPixelToLogic
)
4344 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4346 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4349 long nStartX
= aAreaParam
.maAlignRect
.Left();
4350 long nStartY
= aAreaParam
.maAlignRect
.Top();
4351 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
4352 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
4353 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
4355 // text with automatic breaks is aligned only within the
4356 // edit engine's paper size, the output of the whole area
4357 // is always left-aligned
4361 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
4365 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
4367 aAreaParam
.maClipRect
.Left() = nScrX
;
4368 aAreaParam
.mbLeftClip
= true;
4370 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
4372 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
4373 aAreaParam
.mbRightClip
= true;
4376 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
4377 bool bSimClip
= false;
4381 // Fields in a cell with automatic breaks: clip to cell width
4385 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
4387 aAreaParam
.maClipRect
.Top() = nScrY
;
4390 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
4392 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
4396 Size aCellSize
; // output area, excluding margins, in logical units
4397 if (rParam
.mbPixelToLogic
)
4398 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4400 aCellSize
= Size( nOutWidth
, nOutHeight
);
4402 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4404 const ScMergeAttr
* pMerge
=
4405 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4406 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4408 // Don't clip for text height when printing rows with optimal height,
4409 // except when font size is from conditional formatting.
4410 //! Allow clipping when vertically merged?
4411 if ( eType
!= OUTTYPE_PRINTER
||
4412 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4413 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4414 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4419 // Show clip marks if height is at least 5pt too small and
4420 // there are several lines of text.
4421 // Not for asian vertical text, because that would interfere
4422 // with the default right position of the text.
4423 // Only with automatic line breaks, to avoid having to find
4424 // the cells with the horizontal end of the text again.
4425 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4426 ( rParam
.mbBreak
|| rParam
.meOrient
== SVX_ORIENTATION_STACKED
) &&
4427 !rParam
.mbAsianVertical
&& bMarkClipped
&&
4428 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4430 CellInfo
* pClipMarkCell
= NULL
;
4433 // anywhere in the merged area...
4434 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4435 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4438 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4440 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4443 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4444 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4445 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4449 Rectangle aLogicClip
;
4450 if (bClip
|| bSimClip
)
4452 // Clip marks are already handled in GetOutputArea
4454 if (rParam
.mbPixelToLogic
)
4455 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4457 aLogicClip
= aAreaParam
.maClipRect
;
4459 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4464 mpDev
->IntersectClipRegion( aLogicClip
);
4467 mpDev
->SetClipRegion( Region( aLogicClip
) );
4472 if (rParam
.mbPixelToLogic
)
4473 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4475 aLogicStart
= Point(nStartX
, nStartY
);
4477 long nAvailWidth
= aCellSize
.Width();
4478 // space for AutoFilter is already handled in GetOutputArea
4480 // horizontal alignment
4482 if (rParam
.meHorJustResult
==SVX_HOR_JUSTIFY_RIGHT
)
4483 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
4484 else if (rParam
.meHorJustResult
==SVX_HOR_JUSTIFY_CENTER
)
4485 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
4487 // paper size is subtracted below
4488 aLogicStart
.X() += nEngineWidth
;
4490 // vertical adjustment is within the EditEngine
4491 if (rParam
.mbPixelToLogic
)
4492 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4494 aLogicStart
.Y() += nTopM
;
4496 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4498 rParam
.adjustForRTL();
4500 // bMoveClipped handling has been replaced by complete alignment
4501 // handling (also extending to the left).
4503 // with SetVertical, the start position is top left of
4504 // the whole output area, not the text itself
4505 aLogicStart
.X() -= rParam
.mpEngine
->GetPaperSize().Width();
4507 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
4514 mpDev
->SetClipRegion();
4517 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4520 void ScOutputData::DrawEdit(sal_Bool bPixelToLogic
)
4522 ScFieldEditEngine
* pEngine
= NULL
;
4523 bool bHyphenatorSet
= false;
4524 const ScPatternAttr
* pOldPattern
= NULL
;
4525 const SfxItemSet
* pOldCondSet
= NULL
;
4526 const SfxItemSet
* pOldPreviewFontSet
= NULL
;
4527 ScRefCellValue aCell
;
4529 long nInitPosX
= nScrX
;
4532 nInitPosX
+= nMirrorW
- 1;
4534 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4536 //! store nLastContentCol as member!
4537 SCCOL nLastContentCol
= MAXCOL
;
4539 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
4540 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
4542 long nRowPosY
= nScrY
;
4543 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4545 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4547 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4549 if ( pThisRowInfo
->bChanged
|| nArrY
==0 )
4552 for (SCCOL nX
=0; nX
<=nX2
; nX
++) // wegen Ueberhaengen
4554 std::auto_ptr
< ScPatternAttr
> pPreviewPattr
;
4555 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4557 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4558 if (pInfo
->bEditEngine
)
4560 SCROW nY
= pThisRowInfo
->nRowNo
;
4562 SCCOL nCellX
= nX
; // position where the cell really starts
4564 sal_Bool bDoCell
= false;
4566 long nPosY
= nRowPosY
;
4570 nY
= pRowInfo
[1].nRowNo
;
4571 SCCOL nOverX
; // start of the merged cells
4573 if (GetMergeOrigin( nX
,nY
, 1, nOverX
,nOverY
, sal_True
))
4580 else if ( nX
== nX2
&& pThisRowInfo
->pCellInfo
[nX
+1].maCell
.isEmpty() )
4582 // Rest of a long text further to the right?
4585 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
4589 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
4590 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
4601 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
4604 const ScPatternAttr
* pPattern
= NULL
;
4605 const SfxItemSet
* pCondSet
= NULL
;
4608 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
&&
4609 !mpDoc
->ColHidden(nCellX
, nTab
) )
4611 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
4612 pPattern
= rCellInfo
.pPatternAttr
;
4613 pCondSet
= rCellInfo
.pConditionSet
;
4614 aCell
= rCellInfo
.maCell
;
4616 else // get from document
4618 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
4619 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
4620 GetVisibleCell( nCellX
, nCellY
, nTab
, aCell
);
4622 if (aCell
.isEmpty())
4627 if ( mpDoc
->GetPreviewCellStyle() )
4629 if ( ScStyleSheet
* pPreviewStyle
= mpDoc
->GetPreviewCellStyle( nCellX
, nCellY
, nTab
) )
4631 pPreviewPattr
.reset( new ScPatternAttr(*pPattern
) );
4632 pPreviewPattr
->SetStyleSheet(pPreviewStyle
);
4633 pPattern
= const_cast<ScPatternAttr
*>(pPreviewPattr
.get());
4636 SfxItemSet
* pPreviewFontSet
= mpDoc
->GetPreviewFont( nCellX
, nCellY
, nTab
);
4638 pEngine
= CreateOutputEditEngine();
4640 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4642 // fdo#32530: Check if the first character is RTL.
4643 OUString aStr
= mpDoc
->GetString(nCellX
, nCellY
, nTab
);
4645 DrawEditParam
aParam(pPattern
, pCondSet
, lcl_SafeIsValue(aCell
));
4646 aParam
.meHorJustContext
= getAlignmentFromContext( aParam
.meHorJustAttr
,
4647 aParam
.mbCellIsValue
, aStr
, *pPattern
, pCondSet
, mpDoc
, nTab
);
4648 aParam
.meHorJustResult
= (aParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_BLOCK
) ?
4649 SVX_HOR_JUSTIFY_BLOCK
: aParam
.meHorJustContext
;
4650 aParam
.mbPixelToLogic
= bPixelToLogic
;
4651 aParam
.mbHyphenatorSet
= bHyphenatorSet
;
4652 aParam
.mpEngine
= pEngine
;
4653 aParam
.maCell
= aCell
;
4654 aParam
.mnArrY
= nArrY
;
4657 aParam
.mnCellX
= nCellX
;
4658 aParam
.mnCellY
= nCellY
;
4659 aParam
.mnTab
= nTab
;
4660 aParam
.mnPosX
= nPosX
;
4661 aParam
.mnPosY
= nPosY
;
4662 aParam
.mnInitPosX
= nInitPosX
;
4663 aParam
.mpPreviewFontSet
= pPreviewFontSet
;
4664 aParam
.mpPreviewFontSet
= pPreviewFontSet
;
4665 aParam
.mpOldPattern
= pOldPattern
;
4666 aParam
.mpOldCondSet
= pOldCondSet
;
4667 aParam
.mpOldPreviewFontSet
= pOldPreviewFontSet
;
4668 aParam
.mpThisRowInfo
= pThisRowInfo
;
4669 if (mpSpellCheckCxt
)
4670 aParam
.mpMisspellRanges
= mpSpellCheckCxt
->getMisspellRanges(nCellX
, nCellY
);
4672 if (aParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
)
4674 // ignore orientation/rotation if "repeat" is active
4675 aParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
4677 switch (aParam
.meOrient
)
4679 case SVX_ORIENTATION_BOTTOMTOP
:
4680 DrawEditBottomTop(aParam
);
4682 case SVX_ORIENTATION_TOPBOTTOM
:
4683 DrawEditTopBottom(aParam
);
4685 case SVX_ORIENTATION_STACKED
:
4686 // this can be vertically stacked or asian vertical.
4687 DrawEditStacked(aParam
);
4690 DrawEditStandard(aParam
);
4693 // Retrieve parameters for next iteration.
4694 pOldPattern
= aParam
.mpOldPattern
;
4695 pOldCondSet
= aParam
.mpOldCondSet
;
4696 pOldPreviewFontSet
= aParam
.mpOldPreviewFontSet
;
4697 bHyphenatorSet
= aParam
.mbHyphenatorSet
;
4700 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
4703 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
4709 DrawRotated(bPixelToLogic
); //! von aussen rufen ?
4712 // -------------------------------------------------------------------------------
4714 void ScOutputData::DrawRotated(sal_Bool bPixelToLogic
)
4716 //! nRotMax speichern
4717 SCCOL nRotMax
= nX2
;
4718 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
4719 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
4720 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
4723 ScModule
* pScMod
= SC_MOD();
4724 sal_Int32 nConfBackColor
= pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
4725 sal_Bool bCellContrast
= mbUseStyleColor
&&
4726 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
4728 ScFieldEditEngine
* pEngine
= NULL
;
4729 sal_Bool bHyphenatorSet
= false;
4730 const ScPatternAttr
* pPattern
;
4731 const SfxItemSet
* pCondSet
;
4732 const ScPatternAttr
* pOldPattern
= NULL
;
4733 const SfxItemSet
* pOldCondSet
= NULL
;
4734 ScRefCellValue aCell
;
4736 long nInitPosX
= nScrX
;
4739 nInitPosX
+= nMirrorW
- 1;
4741 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4743 long nRowPosY
= nScrY
;
4744 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4746 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4747 long nCellHeight
= (long) pThisRowInfo
->nHeight
;
4748 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4750 if ( ( pThisRowInfo
->bChanged
|| nArrY
==0 ) && pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
)
4753 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
4755 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4757 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4758 if ( pInfo
->nRotateDir
!= SC_ROTDIR_NONE
)
4760 SCROW nY
= pThisRowInfo
->nRowNo
;
4762 sal_Bool bHidden
= false;
4764 if ( nX
== nEditCol
&& nY
== nEditRow
)
4770 pEngine
= CreateOutputEditEngine();
4772 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4774 long nPosY
= nRowPosY
;
4775 sal_Bool bVisChanged
= false;
4777 //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
4779 sal_Bool bFromDoc
= false;
4780 pPattern
= pInfo
->pPatternAttr
;
4781 pCondSet
= pInfo
->pConditionSet
;
4784 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
4785 bFromDoc
= sal_True
;
4787 aCell
= pInfo
->maCell
;
4789 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
4791 if (aCell
.isEmpty() && nX
>nX2
)
4792 GetVisibleCell( nX
, nY
, nTab
, aCell
);
4794 if (aCell
.isEmpty() || IsEmptyCellText(pThisRowInfo
, nX
, nY
))
4795 bHidden
= true; // nRotateDir is also set without a cell
4797 long nCellWidth
= (long) pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
4799 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)
4800 pPattern
->GetItem(ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
4801 sal_Bool bBreak
= ( eHorJust
== SVX_HOR_JUSTIFY_BLOCK
) ||
4802 ((const SfxBoolItem
&)pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue();
4803 sal_Bool bRepeat
= ( eHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !bBreak
);
4804 sal_Bool bShrink
= !bBreak
&& !bRepeat
&& static_cast<const SfxBoolItem
&>
4805 (pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
4806 SvxCellOrientation eOrient
= pPattern
->GetCellOrientation( pCondSet
);
4808 const ScMergeAttr
* pMerge
=
4809 (ScMergeAttr
*)&pPattern
->GetItem(ATTR_MERGE
);
4810 sal_Bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4812 long nStartX
= nPosX
;
4813 long nStartY
= nPosY
;
4816 if ((bBreak
|| eOrient
!=SVX_ORIENTATION_STANDARD
) && !bMerged
)
4820 nStartX
= nInitPosX
;
4825 nStartX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
4829 long nCellStartX
= nStartX
;
4831 // Ersatzdarstellung fuer zu kleinen Text weggelassen
4835 long nOutWidth
= nCellWidth
- 1;
4836 long nOutHeight
= nCellHeight
;
4838 if ( bMerged
) // Zusammengefasst
4840 SCCOL nCountX
= pMerge
->GetColMerge();
4841 for (SCCOL i
=1; i
<nCountX
; i
++)
4842 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nX
+i
,nTab
) * mnPPTX
);
4843 SCROW nCountY
= pMerge
->GetRowMerge();
4844 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nY
+1, nY
+nCountY
-1, nTab
, mnPPTY
);
4847 SvxCellVerJustify eVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)
4848 pPattern
->GetItem(ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
4850 // Syntax-Modus wird hier ignoriert...
4852 // StringDiffer doesn't look at hyphenate, language items
4853 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
)
4855 SfxItemSet
* pSet
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
4856 pPattern
->FillEditItemSet( pSet
, pCondSet
);
4858 // Ausrichtung fuer EditEngine
4859 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
4860 if (eOrient
==SVX_ORIENTATION_STACKED
)
4861 eSvxAdjust
= SVX_ADJUST_CENTER
;
4862 // Adjustment fuer bBreak ist hier weggelassen
4863 pSet
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
4865 pEngine
->SetDefaults( pSet
);
4866 pOldPattern
= pPattern
;
4867 pOldCondSet
= pCondSet
;
4869 sal_uLong nControl
= pEngine
->GetControlWord();
4870 if (eOrient
==SVX_ORIENTATION_STACKED
)
4871 nControl
|= EE_CNTRL_ONECHARPERLINE
;
4873 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
4874 pEngine
->SetControlWord( nControl
);
4876 if ( !bHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
4878 // set hyphenator the first time it is needed
4879 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
4880 pEngine
->SetHyphenator( xXHyphenator
);
4881 bHyphenatorSet
= sal_True
;
4884 Color aBackCol
= ((const SvxBrushItem
&)
4885 pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
)).GetColor();
4886 if ( mbUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
4887 aBackCol
.SetColor( nConfBackColor
);
4888 pEngine
->SetBackgroundColor( aBackCol
);
4893 //! Position und Papersize auf EditUtil umstellen !!!
4895 const SvxMarginItem
* pMargin
= (const SvxMarginItem
*)
4896 &pPattern
->GetItem(ATTR_MARGIN
, pCondSet
);
4897 sal_uInt16 nIndent
= 0;
4898 if ( eHorJust
== SVX_HOR_JUSTIFY_LEFT
)
4899 nIndent
= ((const SfxUInt16Item
&)pPattern
->
4900 GetItem(ATTR_INDENT
, pCondSet
)).GetValue();
4902 long nTotalHeight
= nOutHeight
; // ohne Rand abzuziehen
4903 if ( bPixelToLogic
)
4904 nTotalHeight
= mpRefDevice
->PixelToLogic(Size(0,nTotalHeight
)).Height();
4906 long nLeftM
= (long) ( (pMargin
->GetLeftMargin() + nIndent
) * mnPPTX
);
4907 long nTopM
= (long) ( pMargin
->GetTopMargin() * mnPPTY
);
4908 long nRightM
= (long) ( pMargin
->GetRightMargin() * mnPPTX
);
4909 long nBottomM
= (long) ( pMargin
->GetBottomMargin() * mnPPTY
);
4912 nOutWidth
-= nLeftM
+ nRightM
;
4913 nOutHeight
-= nTopM
+ nBottomM
;
4915 // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
4916 long nAttrRotate
= 0;
4919 SvxRotateMode eRotMode
= SVX_ROTATE_MODE_STANDARD
;
4920 if ( eOrient
== SVX_ORIENTATION_STANDARD
)
4922 nAttrRotate
= ((const SfxInt32Item
&)pPattern
->
4923 GetItem(ATTR_ROTATE_VALUE
, pCondSet
)).GetValue();
4926 eRotMode
= (SvxRotateMode
)((const SvxRotateModeItem
&)
4927 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
4929 if ( nAttrRotate
== 18000 )
4930 eRotMode
= SVX_ROTATE_MODE_STANDARD
; // keinen Ueberlauf
4933 nAttrRotate
= -nAttrRotate
;
4935 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100 Grad
4936 nCos
= cos( nRealOrient
);
4937 nSin
= sin( nRealOrient
);
4941 Size aPaperSize
= Size( 1000000, 1000000 );
4942 if (eOrient
==SVX_ORIENTATION_STACKED
)
4943 aPaperSize
.Width() = nOutWidth
; // zum Zentrieren
4948 //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
4949 //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
4950 //! werden koennen -> darum unbegrenzt, also kein Umbruch.
4951 //! Mit versetzten Zeilen waere das folgende richtig:
4952 aPaperSize
.Width() = (long)(nOutHeight
/ fabs(nSin
));
4954 else if (eOrient
== SVX_ORIENTATION_STANDARD
)
4955 aPaperSize
.Width() = nOutWidth
;
4957 aPaperSize
.Width() = nOutHeight
- 1;
4960 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4962 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
4964 // Daten aus Zelle lesen
4966 if (aCell
.meType
== CELLTYPE_EDIT
)
4968 if (aCell
.mpEditText
)
4969 pEngine
->SetText(*aCell
.mpEditText
);
4972 OSL_FAIL("pData == 0");
4977 sal_uLong nFormat
= pPattern
->GetNumberFormat(
4978 mpDoc
->GetFormatTable(), pCondSet
);
4981 ScCellFormat::GetString( aCell
,
4982 nFormat
,aString
, &pColor
,
4983 *mpDoc
->GetFormatTable(),
4989 pEngine
->SetText(aString
);
4990 if ( pColor
&& !mbSyntaxMode
&& !( mbUseStyleColor
&& mbForceAutoColor
) )
4991 lcl_SetEditColor( *pEngine
, *pColor
);
4996 SetEditSyntaxColor(*pEngine
, aCell
);
4998 else if ( mbUseStyleColor
&& mbForceAutoColor
)
4999 lcl_SetEditColor( *pEngine
, COL_AUTO
); //! or have a flag at EditEngine
5001 pEngine
->SetUpdateMode( sal_True
); // after SetText, before CalcTextWidth/GetTextHeight
5003 long nEngineWidth
= (long) pEngine
->CalcTextWidth();
5004 long nEngineHeight
= pEngine
->GetTextHeight();
5006 if (nAttrRotate
&& bBreak
)
5008 double nAbsCos
= fabs( nCos
);
5009 double nAbsSin
= fabs( nSin
);
5011 // adjust witdh of papersize for height of text
5015 // everything is in pixels
5016 long nEnginePixel
= mpRefDevice
->LogicToPixel(
5017 Size(0,nEngineHeight
)).Height();
5018 long nEffHeight
= nOutHeight
- (long)(nEnginePixel
* nAbsCos
) + 2;
5019 long nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
5020 sal_Bool bFits
= ( nNewWidth
>= aPaperSize
.Width() );
5025 if ( nNewWidth
< 4 )
5027 // can't fit -> fall back to using half height
5028 nEffHeight
= nOutHeight
/ 2;
5029 nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
5035 // set paper width and get new text height
5036 aPaperSize
.Width() = nNewWidth
;
5038 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
5040 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
5041 //pEngine->QuickFormatDoc( sal_True );
5042 nEngineWidth
= (long) pEngine
->CalcTextWidth();
5043 nEngineHeight
= pEngine
->GetTextHeight();
5048 long nRealWidth
= nEngineWidth
;
5049 long nRealHeight
= nEngineHeight
;
5051 // wenn gedreht, Groesse anpassen
5054 double nAbsCos
= fabs( nCos
);
5055 double nAbsSin
= fabs( nSin
);
5057 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5058 nEngineWidth
= (long) ( nRealWidth
* nAbsCos
+
5059 nRealHeight
* nAbsSin
);
5061 nEngineWidth
= (long) ( nRealHeight
/ nAbsSin
);
5064 nEngineHeight
= (long) ( nRealHeight
* nAbsCos
+
5065 nRealWidth
* nAbsSin
);
5068 if (!nAttrRotate
) // hier nur gedrehter Text
5069 bHidden
= sal_True
; //! vorher abfragen !!!
5071 //! weglassen, was nicht hereinragt
5075 sal_Bool bClip
= false;
5076 Size aClipSize
= Size( nScrX
+nScrW
-nStartX
, nScrY
+nScrH
-nStartY
);
5082 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
5084 aCellSize
= Size( nOutWidth
, nOutHeight
); // Scale ist 1
5086 long nGridWidth
= nEngineWidth
;
5087 sal_Bool bNegative
= false;
5088 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5090 nGridWidth
= aCellSize
.Width() +
5091 std::abs((long) ( aCellSize
.Height() * nCos
/ nSin
));
5092 bNegative
= ( pInfo
->nRotateDir
== SC_ROTDIR_LEFT
);
5094 bNegative
= !bNegative
;
5097 // use GetOutputArea to hide the grid
5098 // (clip region is done manually below)
5099 OutputAreaParam aAreaParam
;
5103 SvxCellHorJustify eOutHorJust
= eHorJust
;
5104 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5105 eOutHorJust
= bNegative
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
5106 long nNeededWidth
= nGridWidth
; // in pixel for GetOutputArea
5107 if ( bPixelToLogic
)
5108 nNeededWidth
= mpRefDevice
->LogicToPixel(Size(nNeededWidth
,0)).Width();
5110 GetOutputArea( nX
, nArrY
, nCellStartX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
5111 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
5112 false, false, sal_True
, aAreaParam
);
5116 long nPixelWidth
= bPixelToLogic
?
5117 mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width() : nEngineWidth
;
5118 long nNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
5120 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= sal_True
;
5123 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5124 false, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5125 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5127 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5129 // do width only if rotating within the cell (standard mode)
5130 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5131 sal_True
, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5132 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5135 // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
5136 // (but width is only valid for standard mode)
5137 nRealWidth
= (long) pEngine
->CalcTextWidth();
5138 nRealHeight
= pEngine
->GetTextHeight();
5140 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5141 nEngineWidth
= (long) ( nRealHeight
/ fabs( nSin
) );
5144 long nClipStartX
= nStartX
;
5147 //! Clipping unnoetig, wenn links am Fenster
5149 bClip
= sal_True
; // nur Rest ausgeben!
5152 long nDif
= nScrX
- nStartX
;
5153 nClipStartX
= nScrX
;
5154 aClipSize
.Width() -= nDif
;
5158 long nClipStartY
= nStartY
;
5159 if (nArrY
==0 || bVisChanged
)
5161 if ( nClipStartY
< nRowPosY
)
5163 long nDif
= nRowPosY
- nClipStartY
;
5165 nClipStartY
= nRowPosY
;
5166 aClipSize
.Height() -= nDif
;
5170 bClip
= sal_True
; // always clip at the window/page border
5172 //Rectangle aClipRect;
5175 if ( nAttrRotate
/* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
5177 // gedrehten, ausgerichteten Text nur an den
5178 // Seitengrenzen clippen
5179 nClipStartX
= nScrX
;
5180 aClipSize
.Width() = nScrW
;
5184 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( Rectangle(
5185 Point(nClipStartX
,nClipStartY
), aClipSize
) );
5187 aAreaParam
.maClipRect
= Rectangle(Point(nClipStartX
, nClipStartY
),
5188 aClipSize
); // Scale = 1
5193 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
5196 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
5201 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
5203 aLogicStart
= Point(nStartX
, nStartY
);
5204 if ( eOrient
!=SVX_ORIENTATION_STANDARD
|| !bBreak
)
5206 long nAvailWidth
= aCellSize
.Width();
5207 if (eType
==OUTTYPE_WINDOW
&&
5208 eOrient
!=SVX_ORIENTATION_STACKED
&&
5209 pInfo
&& pInfo
->bAutoFilter
)
5211 // filter drop-down width is now independent from row height
5213 nAvailWidth
-= mpRefDevice
->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE
)).Height();
5215 nAvailWidth
-= DROPDOWN_BITMAP_SIZE
;
5216 long nComp
= nEngineWidth
;
5217 if (nAvailWidth
<nComp
) nAvailWidth
=nComp
;
5220 // horizontale Ausrichtung
5222 if (eOrient
==SVX_ORIENTATION_STANDARD
&& !nAttrRotate
)
5224 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
||
5225 eHorJust
==SVX_HOR_JUSTIFY_CENTER
)
5227 pEngine
->SetUpdateMode( false );
5229 SvxAdjust eSvxAdjust
=
5230 (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
) ?
5231 SVX_ADJUST_RIGHT
: SVX_ADJUST_CENTER
;
5232 pEngine
->SetDefaultItem(
5233 SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
5235 aPaperSize
.Width() = nOutWidth
;
5237 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
5239 pEngine
->SetPaperSize(aPaperSize
);
5241 pEngine
->SetUpdateMode( sal_True
);
5246 // bei gedrehtem Text ist Standard zentriert
5247 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
)
5248 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
5249 else if (eHorJust
==SVX_HOR_JUSTIFY_CENTER
||
5250 eHorJust
==SVX_HOR_JUSTIFY_STANDARD
)
5251 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
5258 aLogicStart
.X() -= mpRefDevice
->PixelToLogic(
5259 Size( nCellWidth
, 0 ) ).Width();
5261 aLogicStart
.X() -= nCellWidth
;
5264 if ( eOrient
==SVX_ORIENTATION_STANDARD
||
5265 eOrient
==SVX_ORIENTATION_STACKED
|| !bBreak
)
5267 if (eVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
5268 eVerJust
==SVX_VER_JUSTIFY_STANDARD
)
5271 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,
5272 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5273 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
5276 aLogicStart
.Y() += aCellSize
.Height() - nEngineHeight
;
5279 else if (eVerJust
==SVX_VER_JUSTIFY_CENTER
)
5282 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,(
5283 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5284 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height())
5287 aLogicStart
.Y() += (aCellSize
.Height() - nEngineHeight
) / 2;
5291 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
5292 OSL_ENSURE( eOrient
== SVX_ORIENTATION_STANDARD
&& nAttrRotate
,
5293 "DrawRotated: no rotation" );
5298 // Attribut ist 1/100, Font 1/10 Grad
5299 nOriVal
= nAttrRotate
/ 10;
5303 if ( nCos
> 0.0 && eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5306 double nH
= nRealHeight
* nCos
;
5307 nAddX
+= nH
* ( nCos
/ fabs(nSin
) );
5309 if ( nCos
< 0.0 && eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5310 nAddX
-= nRealWidth
* nCos
;
5312 nAddX
-= nRealHeight
* nSin
;
5314 nAddY
+= nRealWidth
* nSin
;
5316 nAddY
-= nRealHeight
* nCos
;
5318 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5321 double nSkew
= nTotalHeight
* nCos
/ fabs(nSin
);
5322 if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
5323 nAddX
-= nSkew
* 0.5;
5324 if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nSin
> 0.0 ) ||
5325 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nSin
< 0.0 ) )
5329 if ( eVerJust
== SVX_VER_JUSTIFY_CENTER
)
5330 nUp
= ( aCellSize
.Height() - nEngineHeight
) / 2;
5331 else if ( eVerJust
== SVX_VER_JUSTIFY_TOP
)
5334 nUp
= aCellSize
.Height() - nEngineHeight
;
5336 else // BOTTOM / STANDARD
5339 nUp
= aCellSize
.Height() - nEngineHeight
;
5342 nAddX
+= ( nUp
* nCos
/ fabs(nSin
) );
5345 aLogicStart
.X() += (long) nAddX
;
5346 aLogicStart
.Y() += (long) nAddY
;
5349 // bSimClip is not used here (because nOriVal is set)
5351 if ( pEngine
->IsRightToLeft( 0 ) )
5353 // For right-to-left, EditEngine always calculates its lines
5354 // beginning from the right edge, but EditLine::nStartPosX is
5355 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
5356 Size aLogicPaper
= pEngine
->GetPaperSize();
5357 if ( aLogicPaper
.Width() > USHRT_MAX
)
5359 aLogicPaper
.Width() = USHRT_MAX
;
5360 pEngine
->SetPaperSize(aLogicPaper
);
5364 pEngine
->Draw( mpDev
, aLogicStart
, (short)nOriVal
);
5371 mpDev
->SetClipRegion();
5377 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
5380 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
5388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */